]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #89551 - jhpratt:stabilize-const_raw_ptr_deref, r=oli-obk
authorbors <bors@rust-lang.org>
Sat, 13 Nov 2021 17:10:15 +0000 (17:10 +0000)
committerbors <bors@rust-lang.org>
Sat, 13 Nov 2021 17:10:15 +0000 (17:10 +0000)
Stabilize `const_raw_ptr_deref` for `*const T`

This stabilizes dereferencing immutable raw pointers in const contexts.
It does not stabilize `*mut T` dereferencing. This is behind the
same feature gate as mutable references.

closes https://github.com/rust-lang/rust/issues/51911

1115 files changed:
Cargo.lock
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/util/comments.rs
compiler/rustc_ast/src/util/parser.rs
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/src/asm.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
compiler/rustc_borrowck/src/nll.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_borrowck/src/universal_regions.rs
compiler/rustc_builtin_macros/src/asm.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/deriving/mod.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/global_allocator.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_builtin_macros/src/test_harness.rs
compiler/rustc_codegen_llvm/src/back/write.rs
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/back/write.rs
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_const_eval/src/const_eval/error.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/fn_queries.rs
compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
compiler/rustc_const_eval/src/interpret/machine.rs
compiler/rustc_const_eval/src/interpret/terminator.rs
compiler/rustc_const_eval/src/interpret/validity.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
compiler/rustc_data_structures/src/steal.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0206.md
compiler/rustc_error_codes/src/error_codes/E0786.md [new file with mode: 0644]
compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/proc_macro.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_incremental/src/persist/fs.rs
compiler/rustc_incremental/src/persist/load.rs
compiler/rustc_infer/src/infer/canonical/query_response.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
compiler/rustc_infer/src/infer/error_reporting/note.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/outlives/env.rs
compiler/rustc_infer/src/traits/engine.rs
compiler/rustc_infer/src/traits/error_reporting/mod.rs
compiler/rustc_interface/src/interface.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lexer/src/unescape.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/internal.rs
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
compiler/rustc_macros/src/hash_stable.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/pretty.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_middle/src/util/common.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_transform/src/coverage/mod.rs
compiler/rustc_mir_transform/src/coverage/spans.rs
compiler/rustc_mir_transform/src/reveal_all.rs
compiler/rustc_mir_transform/src/shim.rs
compiler/rustc_mir_transform/src/unreachable_prop.rs
compiler/rustc_monomorphize/src/partitioning/mod.rs
compiler/rustc_monomorphize/src/polymorphize.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/validate_attr.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/check_const.rs
compiler/rustc_passes/src/region.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_system/src/query/plumbing.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/check_unused.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/imports.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/macros.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_trait_selection/src/autoderef.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
compiler/rustc_trait_selection/src/traits/codegen.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/misc.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/specialize/mod.rs
compiler/rustc_trait_selection/src/traits/structural_match.rs
compiler/rustc_traits/src/implied_outlives_bounds.rs
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_typeck/src/astconv/generics.rs
compiler/rustc_typeck/src/check/cast.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/closure.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/demand.rs
compiler/rustc_typeck/src/check/dropck.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fallback.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check/regionck.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/coherence/builtin.rs
compiler/rustc_typeck/src/coherence/mod.rs
compiler/rustc_typeck/src/coherence/orphan.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/hir_wf_check.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/outlives_bounds.rs
compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
library/alloc/src/boxed.rs
library/alloc/src/lib.rs
library/alloc/src/raw_vec.rs
library/alloc/src/rc.rs
library/backtrace
library/core/src/array/mod.rs
library/core/src/cell.rs
library/core/src/clone.rs
library/core/src/intrinsics.rs
library/core/src/lib.rs
library/core/src/macros/mod.rs
library/core/src/marker.rs
library/core/src/ptr/mut_ptr.rs
library/core/src/slice/mod.rs
library/core/tests/lib.rs
library/core/tests/simd.rs [new file with mode: 0644]
library/portable-simd/.github/ISSUE_TEMPLATE/blank_issue.md [new file with mode: 0644]
library/portable-simd/.github/ISSUE_TEMPLATE/bug_report.md [new file with mode: 0644]
library/portable-simd/.github/ISSUE_TEMPLATE/config.yml [new file with mode: 0644]
library/portable-simd/.github/ISSUE_TEMPLATE/feature_request.md [new file with mode: 0644]
library/portable-simd/.github/PULL_REQUEST_TEMPLATE.md [new file with mode: 0644]
library/portable-simd/.github/workflows/ci.yml [new file with mode: 0644]
library/portable-simd/.github/workflows/doc.yml [new file with mode: 0644]
library/portable-simd/.gitignore [new file with mode: 0644]
library/portable-simd/CONTRIBUTING.md [new file with mode: 0644]
library/portable-simd/Cargo.toml [new file with mode: 0644]
library/portable-simd/LICENSE-APACHE [new file with mode: 0644]
library/portable-simd/LICENSE-MIT [new file with mode: 0644]
library/portable-simd/README.md [new file with mode: 0644]
library/portable-simd/beginners-guide.md [new file with mode: 0644]
library/portable-simd/crates/core_simd/Cargo.toml [new file with mode: 0644]
library/portable-simd/crates/core_simd/LICENSE-APACHE [new file with mode: 0644]
library/portable-simd/crates/core_simd/LICENSE-MIT [new file with mode: 0644]
library/portable-simd/crates/core_simd/examples/matrix_inversion.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/examples/nbody.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/comparisons.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/core_simd_docs.md [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/fmt.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/intrinsics.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/iter.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/lane_count.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/lib.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/masks.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/masks/bitmask.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/masks/full_masks.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/math.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/mod.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/reduction.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/round.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/select.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/swizzle.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/to_bytes.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vector.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vector/float.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vector/int.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vector/ptr.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vector/uint.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vendor.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vendor/arm.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vendor/powerpc.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vendor/wasm32.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/src/vendor/x86.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/f32_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/f64_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/i16_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/i32_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/i64_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/i8_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/isize_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask16.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask32.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask64.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask8.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops_impl/masksize.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/mask_ops_impl/mod.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/masks.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/ops_macros.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/round.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/swizzle.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/to_bytes.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/u16_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/u32_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/u64_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/u8_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/tests/usize_ops.rs [new file with mode: 0644]
library/portable-simd/crates/core_simd/webdriver.json [new file with mode: 0644]
library/portable-simd/crates/test_helpers/Cargo.toml [new file with mode: 0644]
library/portable-simd/crates/test_helpers/src/array.rs [new file with mode: 0644]
library/portable-simd/crates/test_helpers/src/biteq.rs [new file with mode: 0644]
library/portable-simd/crates/test_helpers/src/lib.rs [new file with mode: 0644]
library/portable-simd/crates/test_helpers/src/wasm.rs [new file with mode: 0644]
library/proc_macro/src/bridge/mod.rs
library/proc_macro/src/lib.rs
library/std/src/collections/mod.rs
library/std/src/keyword_docs.rs
library/std/src/lib.rs
library/std/src/net/ip.rs
library/std/src/os/unix/net/addr.rs
library/std/src/os/unix/process.rs
library/std/src/os/windows/io/handle.rs
library/std/src/process.rs
library/std/src/sys/solid/abi/mod.rs
library/std/src/sys/unix/process/process_unix.rs
library/std/src/sys/unix/thread.rs
rustfmt.toml
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/bootstrap/util.rs
src/doc/book
src/doc/edition-guide
src/doc/nomicon
src/doc/rust-by-example
src/doc/rustc-dev-guide
src/doc/rustdoc/src/SUMMARY.md
src/doc/rustdoc/src/how-to-read-rustdoc.md [new file with mode: 0644]
src/doc/unstable-book/src/compiler-flags/temps-dir.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/type-changing-struct-update.md [new file with mode: 0644]
src/doc/unstable-book/src/library-features/asm.md
src/doc/unstable-book/src/library-features/global-asm.md
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/formats/cache.rs
src/librustdoc/formats/item_type.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render/cache.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/json/conversions.rs
src/librustdoc/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_intra_doc_links/early.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/scrape_examples.rs
src/librustdoc/visit_ast.rs
src/librustdoc/visit_lib.rs
src/llvm-project
src/test/assembly/asm/aarch64-types.rs
src/test/assembly/asm/arm-types.rs
src/test/assembly/asm/bpf-types.rs
src/test/assembly/asm/global_asm.rs
src/test/assembly/asm/hexagon-types.rs
src/test/assembly/asm/mips-types.rs
src/test/assembly/asm/nvptx-types.rs
src/test/assembly/asm/powerpc-types.rs
src/test/assembly/asm/riscv-types.rs
src/test/assembly/asm/s390x-types.rs
src/test/assembly/asm/wasm-types.rs
src/test/assembly/asm/x86-types.rs
src/test/codegen/array-clone.rs [new file with mode: 0644]
src/test/codegen/asm-powerpc-clobbers.rs
src/test/mir-opt/issue-78192.rs
src/test/pretty/dollar-crate.pp
src/test/pretty/issue-4264.pp
src/test/run-make-fulldeps/invalid-library/Makefile
src/test/run-make-fulldeps/print-cfg/Makefile
src/test/run-make/invalid-so/Makefile [new file with mode: 0644]
src/test/run-make/invalid-so/bar.rs [new file with mode: 0644]
src/test/run-make/issue-10971-temps-dir/Makefile [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/extern-crate-load.rs [new file with mode: 0644]
src/test/rustdoc/include_str_cut.rs [new file with mode: 0644]
src/test/rustdoc/short-line.md [new file with mode: 0644]
src/test/ui-fulldeps/lint-tool-test.rs
src/test/ui-fulldeps/lint-tool-test.stderr
src/test/ui/argument-passing.rs [deleted file]
src/test/ui/array-slice-vec/mut-vstore-expr.rs [new file with mode: 0644]
src/test/ui/asm/aarch64/bad-reg.rs
src/test/ui/asm/aarch64/const.rs
src/test/ui/asm/aarch64/parse-error.rs
src/test/ui/asm/aarch64/parse-error.stderr
src/test/ui/asm/aarch64/sym.rs
src/test/ui/asm/aarch64/type-check-2.rs
src/test/ui/asm/aarch64/type-check-3.rs
src/test/ui/asm/aarch64/type-check-3.stderr
src/test/ui/asm/bad-template.rs
src/test/ui/asm/issue-89305.rs
src/test/ui/asm/issue-89305.stderr
src/test/ui/asm/naked-functions.rs
src/test/ui/asm/naked-functions.stderr
src/test/ui/asm/named-asm-labels.rs
src/test/ui/asm/type-check-1.rs
src/test/ui/asm/x86_64/bad-clobber-abi.rs [new file with mode: 0644]
src/test/ui/asm/x86_64/bad-clobber-abi.stderr [new file with mode: 0644]
src/test/ui/asm/x86_64/bad-options.rs
src/test/ui/asm/x86_64/bad-options.stderr
src/test/ui/asm/x86_64/bad-reg.rs
src/test/ui/asm/x86_64/const.rs
src/test/ui/asm/x86_64/multiple-clobber-abi.rs [new file with mode: 0644]
src/test/ui/asm/x86_64/parse-error.rs
src/test/ui/asm/x86_64/parse-error.stderr
src/test/ui/asm/x86_64/sym.rs
src/test/ui/asm/x86_64/type-check-2.rs
src/test/ui/asm/x86_64/type-check-3.rs
src/test/ui/associated-types/issue-22066.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-22828.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-28871.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-47139-1.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-54467.rs [new file with mode: 0644]
src/test/ui/async-await/issue-73541-1.rs [new file with mode: 0644]
src/test/ui/async-await/issue-73541-1.stderr [new file with mode: 0644]
src/test/ui/attributes/issue-40962.rs [new file with mode: 0644]
src/test/ui/attributes/key-value-expansion.stderr
src/test/ui/attributes/unrestricted-attribute-tokens.rs [new file with mode: 0644]
src/test/ui/auxiliary/changing-crates-a1.rs [deleted file]
src/test/ui/auxiliary/changing-crates-a2.rs [deleted file]
src/test/ui/auxiliary/changing-crates-b.rs [deleted file]
src/test/ui/auxiliary/legacy-const-generics.rs [deleted file]
src/test/ui/auxiliary/lto-duplicate-symbols1.rs [deleted file]
src/test/ui/auxiliary/lto-duplicate-symbols2.rs [deleted file]
src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs [deleted file]
src/test/ui/auxiliary/nested_item.rs [deleted file]
src/test/ui/bastion-of-the-turbofish.rs [deleted file]
src/test/ui/binop/structured-compare.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-46095.rs [new file with mode: 0644]
src/test/ui/box/new-box.rs [new file with mode: 0644]
src/test/ui/builtin-clone-unwind.rs
src/test/ui/c-variadic/issue-32201.rs [new file with mode: 0644]
src/test/ui/c-variadic/issue-32201.stderr [new file with mode: 0644]
src/test/ui/cast/supported-cast.rs [new file with mode: 0644]
src/test/ui/chalkify/builtin-copy-clone.rs
src/test/ui/changing-crates.rs [deleted file]
src/test/ui/changing-crates.stderr [deleted file]
src/test/ui/closures/issue-10398.rs [new file with mode: 0644]
src/test/ui/closures/issue-10398.stderr [new file with mode: 0644]
src/test/ui/closures/issue-42463.rs [new file with mode: 0644]
src/test/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
src/test/ui/closures/print/closure-print-generic-verbose-2.stderr
src/test/ui/coercion/auxiliary/issue-39823.rs [new file with mode: 0644]
src/test/ui/coercion/issue-14589.rs [new file with mode: 0644]
src/test/ui/coercion/issue-39823.rs [new file with mode: 0644]
src/test/ui/coercion/issue-73886.rs [new file with mode: 0644]
src/test/ui/coercion/issue-73886.stderr [new file with mode: 0644]
src/test/ui/coherence/coherence-cross-crate-conflict.rs
src/test/ui/coherence/coherence-cross-crate-conflict.stderr
src/test/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
src/test/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
src/test/ui/coherence/coherence-impls-copy.rs
src/test/ui/coherence/coherence-impls-copy.stderr
src/test/ui/coherence/coherence-impls-send.rs
src/test/ui/coherence/coherence-impls-send.stderr
src/test/ui/coherence/coherence-impls-sized.stderr
src/test/ui/coherence/coherence-orphan.stderr
src/test/ui/command/command-pre-exec.rs
src/test/ui/compare-method/issue-90444.rs [new file with mode: 0644]
src/test/ui/compare-method/issue-90444.stderr [new file with mode: 0644]
src/test/ui/conditional-compilation/issue-34028.rs [new file with mode: 0644]
src/test/ui/const-generics/auxiliary/legacy-const-generics.rs [new file with mode: 0644]
src/test/ui/const-generics/impl-trait-with-const-arguments.stderr
src/test/ui/const-generics/legacy-const-generics-bad.rs [new file with mode: 0644]
src/test/ui/const-generics/legacy-const-generics-bad.stderr [new file with mode: 0644]
src/test/ui/const-generics/legacy-const-generics.rs [new file with mode: 0644]
src/test/ui/consts/inline_asm.rs
src/test/ui/consts/inline_asm.stderr
src/test/ui/consts/issue-13902.rs [new file with mode: 0644]
src/test/ui/consts/issue-17074.rs [new file with mode: 0644]
src/test/ui/consts/issue-18294.rs [new file with mode: 0644]
src/test/ui/consts/issue-18294.stderr [new file with mode: 0644]
src/test/ui/consts/issue-23968-const-not-overflow.rs [new file with mode: 0644]
src/test/ui/consts/issue-37550-1.rs [new file with mode: 0644]
src/test/ui/consts/issue-37550-1.stderr [new file with mode: 0644]
src/test/ui/consts/issue-37991.rs [new file with mode: 0644]
src/test/ui/crate-loading/auxiliary/libfoo.rlib [new file with mode: 0644]
src/test/ui/crate-loading/invalid-rlib.rs [new file with mode: 0644]
src/test/ui/crate-loading/invalid-rlib.stderr [new file with mode: 0644]
src/test/ui/deprecation/deprecation-lint.rs
src/test/ui/deprecation/deprecation-lint.stderr
src/test/ui/deprecation/try-macro-suggestion.rs [new file with mode: 0644]
src/test/ui/deprecation/try-macro-suggestion.stderr [new file with mode: 0644]
src/test/ui/deriving/issue-19358.rs [new file with mode: 0644]
src/test/ui/deriving/issue-58319.rs [new file with mode: 0644]
src/test/ui/diverging-tuple-parts-39485.rs [deleted file]
src/test/ui/diverging-tuple-parts-39485.stderr [deleted file]
src/test/ui/drop/issue-35546.rs [new file with mode: 0644]
src/test/ui/drop/terminate-in-initializer.rs [new file with mode: 0644]
src/test/ui/dropck/drop-on-non-struct.stderr
src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs [new file with mode: 0644]
src/test/ui/editions-crate-root-2015.rs [deleted file]
src/test/ui/editions-crate-root-2015.stderr [deleted file]
src/test/ui/editions/epoch-gate-feature.rs [new file with mode: 0644]
src/test/ui/enum-discriminant/issue-51582.rs [new file with mode: 0644]
src/test/ui/enum/issue-42747.rs [new file with mode: 0644]
src/test/ui/epoch-gate-feature.rs [deleted file]
src/test/ui/error-codes/E0117.stderr
src/test/ui/error-codes/E0206.rs
src/test/ui/error-codes/E0206.stderr
src/test/ui/error-codes/e0119/complex-impl.rs
src/test/ui/error-codes/e0119/complex-impl.stderr
src/test/ui/error-codes/e0119/issue-28981.rs
src/test/ui/error-codes/e0119/issue-28981.stderr
src/test/ui/extern/issue-28324.mir.stderr [new file with mode: 0644]
src/test/ui/extern/issue-28324.rs [new file with mode: 0644]
src/test/ui/extern/issue-28324.thir.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_const.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_const.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_sym.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-asm_sym.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs [deleted file]
src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr [deleted file]
src/test/ui/for-loop-while/issue-51345.rs [new file with mode: 0644]
src/test/ui/for-loop-while/long-while.rs [new file with mode: 0644]
src/test/ui/foreign/nil-decl-in-foreign.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-88595.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-88595.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-90014.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-90014.stderr [new file with mode: 0644]
src/test/ui/generics/issue-1112.rs [new file with mode: 0644]
src/test/ui/generics/issue-333.rs [new file with mode: 0644]
src/test/ui/generics/issue-59508-1.rs [new file with mode: 0644]
src/test/ui/generics/issue-59508-1.stderr [new file with mode: 0644]
src/test/ui/generics/issue-59508.fixed [new file with mode: 0644]
src/test/ui/generics/issue-59508.rs [new file with mode: 0644]
src/test/ui/generics/issue-59508.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/issue-60283.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/issue-60283.stderr [new file with mode: 0644]
src/test/ui/hygiene/lambda-var-hygiene.rs [new file with mode: 0644]
src/test/ui/impl-trait/explicit-generic-args-with-impl-trait/feature-gate.stderr
src/test/ui/impl-trait/issue-49579.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-49685.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-51185.rs [new file with mode: 0644]
src/test/ui/impl-trait/issues/universal-issue-48703.stderr
src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr
src/test/ui/impl-trait/where-allowed.rs
src/test/ui/impl-trait/where-allowed.stderr
src/test/ui/in-band-lifetimes.rs [deleted file]
src/test/ui/in-band-lifetimes/in-band-lifetimes.rs [new file with mode: 0644]
src/test/ui/inference/lub-glb-with-unbound-infer-var.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-inference.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime-err.rs [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime-err.stderr [new file with mode: 0644]
src/test/ui/inline-const/const-expr-lifetime.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-inference.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-lifetime-err.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-lifetime.rs [new file with mode: 0644]
src/test/ui/intrinsics/intrinsic-alignment.rs
src/test/ui/issues/auxiliary/issue-19163.rs [deleted file]
src/test/ui/issues/auxiliary/issue-39823.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs [deleted file]
src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs [deleted file]
src/test/ui/issues/issue-10398.rs [deleted file]
src/test/ui/issues/issue-10398.stderr [deleted file]
src/test/ui/issues/issue-1112.rs [deleted file]
src/test/ui/issues/issue-11577.rs [deleted file]
src/test/ui/issues/issue-11940.rs [deleted file]
src/test/ui/issues/issue-12796.rs [deleted file]
src/test/ui/issues/issue-12796.stderr [deleted file]
src/test/ui/issues/issue-13483.rs [deleted file]
src/test/ui/issues/issue-13483.stderr [deleted file]
src/test/ui/issues/issue-13902.rs [deleted file]
src/test/ui/issues/issue-14227.mir.stderr [deleted file]
src/test/ui/issues/issue-14227.rs [deleted file]
src/test/ui/issues/issue-14227.thir.stderr [deleted file]
src/test/ui/issues/issue-14456.rs [deleted file]
src/test/ui/issues/issue-14589.rs [deleted file]
src/test/ui/issues/issue-14837.rs [deleted file]
src/test/ui/issues/issue-15080.rs [deleted file]
src/test/ui/issues/issue-16098.rs [deleted file]
src/test/ui/issues/issue-16098.stderr [deleted file]
src/test/ui/issues/issue-16272.rs [deleted file]
src/test/ui/issues/issue-17074.rs [deleted file]
src/test/ui/issues/issue-18060.rs [deleted file]
src/test/ui/issues/issue-18294.rs [deleted file]
src/test/ui/issues/issue-18294.stderr [deleted file]
src/test/ui/issues/issue-18652.rs [deleted file]
src/test/ui/issues/issue-19163.rs [deleted file]
src/test/ui/issues/issue-19163.stderr [deleted file]
src/test/ui/issues/issue-19358.rs [deleted file]
src/test/ui/issues/issue-19660.rs [deleted file]
src/test/ui/issues/issue-19660.stderr [deleted file]
src/test/ui/issues/issue-20091.rs [deleted file]
src/test/ui/issues/issue-20616-4.rs [deleted file]
src/test/ui/issues/issue-20616-4.stderr [deleted file]
src/test/ui/issues/issue-20616-5.rs [deleted file]
src/test/ui/issues/issue-20616-5.stderr [deleted file]
src/test/ui/issues/issue-20616-6.rs [deleted file]
src/test/ui/issues/issue-20616-6.stderr [deleted file]
src/test/ui/issues/issue-20616-7.rs [deleted file]
src/test/ui/issues/issue-20616-7.stderr [deleted file]
src/test/ui/issues/issue-20823.rs [deleted file]
src/test/ui/issues/issue-21356.rs [deleted file]
src/test/ui/issues/issue-21356.stderr [deleted file]
src/test/ui/issues/issue-21475.rs [deleted file]
src/test/ui/issues/issue-21520.rs [deleted file]
src/test/ui/issues/issue-22066.rs [deleted file]
src/test/ui/issues/issue-22463.rs [deleted file]
src/test/ui/issues/issue-22828.rs [deleted file]
src/test/ui/issues/issue-23458.rs [deleted file]
src/test/ui/issues/issue-23458.stderr [deleted file]
src/test/ui/issues/issue-23716.rs [deleted file]
src/test/ui/issues/issue-23716.stderr [deleted file]
src/test/ui/issues/issue-23968-const-not-overflow.rs [deleted file]
src/test/ui/issues/issue-24010.rs [deleted file]
src/test/ui/issues/issue-24313.rs [deleted file]
src/test/ui/issues/issue-2444.rs [deleted file]
src/test/ui/issues/issue-26251.rs [deleted file]
src/test/ui/issues/issue-26448-1.rs [deleted file]
src/test/ui/issues/issue-26448-2.rs [deleted file]
src/test/ui/issues/issue-26448-3.rs [deleted file]
src/test/ui/issues/issue-26638.rs [deleted file]
src/test/ui/issues/issue-26638.stderr [deleted file]
src/test/ui/issues/issue-26996.rs [deleted file]
src/test/ui/issues/issue-2748-b.rs [deleted file]
src/test/ui/issues/issue-28324.mir.stderr [deleted file]
src/test/ui/issues/issue-28324.rs [deleted file]
src/test/ui/issues/issue-28324.thir.stderr [deleted file]
src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs [deleted file]
src/test/ui/issues/issue-28871.rs [deleted file]
src/test/ui/issues/issue-29084.rs [deleted file]
src/test/ui/issues/issue-29084.stderr [deleted file]
src/test/ui/issues/issue-3021-c.rs [deleted file]
src/test/ui/issues/issue-3021-c.stderr [deleted file]
src/test/ui/issues/issue-3021.rs [deleted file]
src/test/ui/issues/issue-3021.stderr [deleted file]
src/test/ui/issues/issue-30225.rs [deleted file]
src/test/ui/issues/issue-30225.stderr [deleted file]
src/test/ui/issues/issue-30355.rs [deleted file]
src/test/ui/issues/issue-30355.stderr [deleted file]
src/test/ui/issues/issue-31076.rs [deleted file]
src/test/ui/issues/issue-31076.stderr [deleted file]
src/test/ui/issues/issue-31804.rs [deleted file]
src/test/ui/issues/issue-31804.stderr [deleted file]
src/test/ui/issues/issue-31845.rs [deleted file]
src/test/ui/issues/issue-31845.stderr [deleted file]
src/test/ui/issues/issue-3211.rs [deleted file]
src/test/ui/issues/issue-32201.rs [deleted file]
src/test/ui/issues/issue-32201.stderr [deleted file]
src/test/ui/issues/issue-333.rs [deleted file]
src/test/ui/issues/issue-34028.rs [deleted file]
src/test/ui/issues/issue-34171.rs [deleted file]
src/test/ui/issues/issue-34255-1.rs [deleted file]
src/test/ui/issues/issue-34255-1.stderr [deleted file]
src/test/ui/issues/issue-35546.rs [deleted file]
src/test/ui/issues/issue-37175.rs [deleted file]
src/test/ui/issues/issue-37366.rs [deleted file]
src/test/ui/issues/issue-37550.rs [deleted file]
src/test/ui/issues/issue-37550.stderr [deleted file]
src/test/ui/issues/issue-37991.rs [deleted file]
src/test/ui/issues/issue-38604.rs [deleted file]
src/test/ui/issues/issue-38604.stderr [deleted file]
src/test/ui/issues/issue-39388.rs [deleted file]
src/test/ui/issues/issue-39388.stderr [deleted file]
src/test/ui/issues/issue-3973.rs [deleted file]
src/test/ui/issues/issue-3973.stderr [deleted file]
src/test/ui/issues/issue-39823.rs [deleted file]
src/test/ui/issues/issue-40770.rs [deleted file]
src/test/ui/issues/issue-40962.rs [deleted file]
src/test/ui/issues/issue-41974.rs
src/test/ui/issues/issue-41974.stderr
src/test/ui/issues/issue-42463.rs [deleted file]
src/test/ui/issues/issue-42679.rs [deleted file]
src/test/ui/issues/issue-42747.rs [deleted file]
src/test/ui/issues/issue-43189.rs [deleted file]
src/test/ui/issues/issue-43189.stderr [deleted file]
src/test/ui/issues/issue-4401.rs [deleted file]
src/test/ui/issues/issue-4448.rs [deleted file]
src/test/ui/issues/issue-45124.rs [deleted file]
src/test/ui/issues/issue-45152.rs [deleted file]
src/test/ui/issues/issue-46095.rs [deleted file]
src/test/ui/issues/issue-46112.rs [deleted file]
src/test/ui/issues/issue-46112.stderr [deleted file]
src/test/ui/issues/issue-47139-1.rs [deleted file]
src/test/ui/issues/issue-49040.rs [deleted file]
src/test/ui/issues/issue-49040.stderr [deleted file]
src/test/ui/issues/issue-49579.rs [deleted file]
src/test/ui/issues/issue-49685.rs [deleted file]
src/test/ui/issues/issue-50731.rs [deleted file]
src/test/ui/issues/issue-5099.rs [deleted file]
src/test/ui/issues/issue-5099.stderr [deleted file]
src/test/ui/issues/issue-50993.rs [deleted file]
src/test/ui/issues/issue-50993.stderr [deleted file]
src/test/ui/issues/issue-51185.rs [deleted file]
src/test/ui/issues/issue-51345.rs [deleted file]
src/test/ui/issues/issue-51582.rs [deleted file]
src/test/ui/issues/issue-53787-inline-assembler-macro.rs [deleted file]
src/test/ui/issues/issue-53787-inline-assembler-macro.stderr [deleted file]
src/test/ui/issues/issue-54467.rs [deleted file]
src/test/ui/issues/issue-56031.rs [deleted file]
src/test/ui/issues/issue-56031.stderr [deleted file]
src/test/ui/issues/issue-57410-1.rs [deleted file]
src/test/ui/issues/issue-57597.rs [deleted file]
src/test/ui/issues/issue-57597.stderr [deleted file]
src/test/ui/issues/issue-58319.rs [deleted file]
src/test/ui/issues/issue-59029-1.rs [deleted file]
src/test/ui/issues/issue-59029-1.stderr [deleted file]
src/test/ui/issues/issue-59508-1.rs [deleted file]
src/test/ui/issues/issue-59508-1.stderr [deleted file]
src/test/ui/issues/issue-59508.fixed [deleted file]
src/test/ui/issues/issue-59508.rs [deleted file]
src/test/ui/issues/issue-59508.stderr [deleted file]
src/test/ui/issues/issue-60283.rs [deleted file]
src/test/ui/issues/issue-60283.stderr [deleted file]
src/test/ui/issues/issue-60662.rs [deleted file]
src/test/ui/issues/issue-60662.stdout [deleted file]
src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs [deleted file]
src/test/ui/issues/issue-61882-2.rs [deleted file]
src/test/ui/issues/issue-61882-2.stderr [deleted file]
src/test/ui/issues/issue-61882.rs [deleted file]
src/test/ui/issues/issue-61882.stderr [deleted file]
src/test/ui/issues/issue-63364.rs [deleted file]
src/test/ui/issues/issue-63364.stderr [deleted file]
src/test/ui/issues/issue-6596-1.rs [deleted file]
src/test/ui/issues/issue-6596-1.stderr [deleted file]
src/test/ui/issues/issue-6804.rs [deleted file]
src/test/ui/issues/issue-6804.stderr [deleted file]
src/test/ui/issues/issue-72455.rs [deleted file]
src/test/ui/issues/issue-7246.rs
src/test/ui/issues/issue-7246.stderr
src/test/ui/issues/issue-72574-2.rs [deleted file]
src/test/ui/issues/issue-72574-2.stderr [deleted file]
src/test/ui/issues/issue-73541-1.rs [deleted file]
src/test/ui/issues/issue-73541-1.stderr [deleted file]
src/test/ui/issues/issue-73886.rs [deleted file]
src/test/ui/issues/issue-73886.stderr [deleted file]
src/test/ui/issues/issue-74739.rs [deleted file]
src/test/ui/issues/issue-811.rs [deleted file]
src/test/ui/issues/issue-8351-1.rs [deleted file]
src/test/ui/issues/issue-8351-2.rs [deleted file]
src/test/ui/issues/issue-86865.rs [deleted file]
src/test/ui/issues/issue-86865.stderr [deleted file]
src/test/ui/issues/issue-8827.rs [deleted file]
src/test/ui/issues/issue-9396.rs [deleted file]
src/test/ui/lambda-var-hygiene.rs [deleted file]
src/test/ui/lang-items/issue-19660.rs [new file with mode: 0644]
src/test/ui/lang-items/issue-19660.stderr [new file with mode: 0644]
src/test/ui/lang-items/issue-31076.rs [new file with mode: 0644]
src/test/ui/lang-items/issue-31076.stderr [new file with mode: 0644]
src/test/ui/lang-items/required-lang-item.rs [new file with mode: 0644]
src/test/ui/lang-items/required-lang-item.stderr [new file with mode: 0644]
src/test/ui/legacy-const-generics-bad.rs [deleted file]
src/test/ui/legacy-const-generics-bad.stderr [deleted file]
src/test/ui/legacy-const-generics.rs [deleted file]
src/test/ui/lifetimes/issue-26638.rs [new file with mode: 0644]
src/test/ui/lifetimes/issue-26638.stderr [new file with mode: 0644]
src/test/ui/lint/crate_level_only_lint.rs
src/test/ui/lint/crate_level_only_lint.stderr
src/test/ui/lint/forbid-group-group-2.rs
src/test/ui/lint/forbid-group-group-2.stderr
src/test/ui/lint/issue-14837.rs [new file with mode: 0644]
src/test/ui/lint/issue-57410-1.rs [new file with mode: 0644]
src/test/ui/lint/issue-63364.rs [new file with mode: 0644]
src/test/ui/lint/issue-63364.stderr [new file with mode: 0644]
src/test/ui/lint/lint-forbid-internal-unsafe.rs
src/test/ui/lint/lint-forbid-internal-unsafe.stderr
src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs
src/test/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr
src/test/ui/lint/unnecessary-extern-crate.rs [new file with mode: 0644]
src/test/ui/lint/unnecessary-extern-crate.stderr [new file with mode: 0644]
src/test/ui/lint/unused/issue-70041.stderr
src/test/ui/lint/unused/unused-macro-rules.stderr
src/test/ui/lint/unused/unused-macro.stderr
src/test/ui/lint/warn-ctypes-inhibit.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-23458.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-23458.stderr [new file with mode: 0644]
src/test/ui/llvm-asm/issue-37366.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr [new file with mode: 0644]
src/test/ui/long-while.rs [deleted file]
src/test/ui/lto-and-no-bitcode-in-rlib.rs [deleted file]
src/test/ui/lto-and-no-bitcode-in-rlib.stderr [deleted file]
src/test/ui/lto-duplicate-symbols.rs [deleted file]
src/test/ui/lto-duplicate-symbols.stderr [deleted file]
src/test/ui/lto-many-codegen-units.rs [deleted file]
src/test/ui/lto-opt-level-s.rs [deleted file]
src/test/ui/lto-opt-level-z.rs [deleted file]
src/test/ui/lto-rustc-loads-linker-plugin.rs [deleted file]
src/test/ui/lto-still-runs-thread-dtors.rs [deleted file]
src/test/ui/lto-thin-rustc-loads-linker-plugin.rs [deleted file]
src/test/ui/lto/all-crates.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/dylib.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/msvc-imp-present.rs [new file with mode: 0644]
src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs [new file with mode: 0644]
src/test/ui/lto/dylib-works.rs [new file with mode: 0644]
src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs [new file with mode: 0644]
src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr [new file with mode: 0644]
src/test/ui/lto/lto-duplicate-symbols.rs [new file with mode: 0644]
src/test/ui/lto/lto-duplicate-symbols.stderr [new file with mode: 0644]
src/test/ui/lto/lto-many-codegen-units.rs [new file with mode: 0644]
src/test/ui/lto/lto-opt-level-s.rs [new file with mode: 0644]
src/test/ui/lto/lto-opt-level-z.rs [new file with mode: 0644]
src/test/ui/lto/lto-rustc-loads-linker-plugin.rs [new file with mode: 0644]
src/test/ui/lto/lto-still-runs-thread-dtors.rs [new file with mode: 0644]
src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs [new file with mode: 0644]
src/test/ui/lto/msvc-imp-present.rs [new file with mode: 0644]
src/test/ui/lto/thin-lto-global-allocator.rs [new file with mode: 0644]
src/test/ui/lto/thin-lto-inlines.rs [new file with mode: 0644]
src/test/ui/lto/thin-lto-inlines2.rs [new file with mode: 0644]
src/test/ui/lto/weak-works.rs [new file with mode: 0644]
src/test/ui/lub-glb-with-unbound-infer-var.rs [deleted file]
src/test/ui/macros/auxiliary/issue-19163.rs [new file with mode: 0644]
src/test/ui/macros/issue-16098.rs [new file with mode: 0644]
src/test/ui/macros/issue-16098.stderr [new file with mode: 0644]
src/test/ui/macros/issue-19163.rs [new file with mode: 0644]
src/test/ui/macros/issue-19163.stderr [new file with mode: 0644]
src/test/ui/macros/issue-21356.rs [new file with mode: 0644]
src/test/ui/macros/issue-21356.stderr [new file with mode: 0644]
src/test/ui/macros/issue-22463.rs [new file with mode: 0644]
src/test/ui/macros/issue-29084.rs [new file with mode: 0644]
src/test/ui/macros/issue-29084.stderr [new file with mode: 0644]
src/test/ui/macros/issue-34171.rs [new file with mode: 0644]
src/test/ui/macros/issue-37175.rs [new file with mode: 0644]
src/test/ui/macros/issue-39388.rs [new file with mode: 0644]
src/test/ui/macros/issue-39388.stderr [new file with mode: 0644]
src/test/ui/macros/issue-40770.rs [new file with mode: 0644]
src/test/ui/macros/issue-57597.rs [new file with mode: 0644]
src/test/ui/macros/issue-57597.stderr [new file with mode: 0644]
src/test/ui/macros/issue-6596-1.rs [new file with mode: 0644]
src/test/ui/macros/issue-6596-1.stderr [new file with mode: 0644]
src/test/ui/macros/issue-86865.rs [new file with mode: 0644]
src/test/ui/macros/issue-86865.stderr [new file with mode: 0644]
src/test/ui/macros/trace_macros-format.rs [new file with mode: 0644]
src/test/ui/macros/trace_macros-format.stderr [new file with mode: 0644]
src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs [new file with mode: 0644]
src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr [new file with mode: 0644]
src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs [new file with mode: 0644]
src/test/ui/match/issue-11940.rs [new file with mode: 0644]
src/test/ui/match/issue-18060.rs [new file with mode: 0644]
src/test/ui/match/issue-26251.rs [new file with mode: 0644]
src/test/ui/match/issue-26996.rs [new file with mode: 0644]
src/test/ui/match/issue-42679.rs [new file with mode: 0644]
src/test/ui/mir/issue-74739.rs [new file with mode: 0644]
src/test/ui/mut-vstore-expr.rs [deleted file]
src/test/ui/negative.rs [deleted file]
src/test/ui/nested_item_main.rs [deleted file]
src/test/ui/never_type/diverging-tuple-parts-39485.rs [new file with mode: 0644]
src/test/ui/never_type/diverging-tuple-parts-39485.stderr [new file with mode: 0644]
src/test/ui/new-box.rs [deleted file]
src/test/ui/nil-decl-in-foreign.rs [deleted file]
src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs [new file with mode: 0644]
src/test/ui/object-does-not-impl-trait.rs [deleted file]
src/test/ui/object-does-not-impl-trait.stderr [deleted file]
src/test/ui/overlap-doesnt-conflict-with-specialization.rs [deleted file]
src/test/ui/overlap-doesnt-conflict-with-specialization.stderr [deleted file]
src/test/ui/overlap-permitted-for-annotated-marker-traits.rs [deleted file]
src/test/ui/packed/issue-46152.rs [new file with mode: 0644]
src/test/ui/parser/bastion-of-the-turbofish.rs [new file with mode: 0644]
src/test/ui/parser/issue-13483.rs [new file with mode: 0644]
src/test/ui/parser/issue-13483.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-4.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-4.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-5.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-5.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-6.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-6.stderr [new file with mode: 0644]
src/test/ui/parser/issue-20616-7.rs [new file with mode: 0644]
src/test/ui/parser/issue-20616-7.stderr [new file with mode: 0644]
src/test/ui/parser/issue-21475.rs [new file with mode: 0644]
src/test/ui/parser/issue-31804.rs [new file with mode: 0644]
src/test/ui/parser/issue-31804.stderr [new file with mode: 0644]
src/test/ui/parser/issue-34255-1.rs [new file with mode: 0644]
src/test/ui/parser/issue-34255-1.stderr [new file with mode: 0644]
src/test/ui/parser/issue-49040.rs [new file with mode: 0644]
src/test/ui/parser/issue-49040.stderr [new file with mode: 0644]
src/test/ui/parser/issue-56031.rs [new file with mode: 0644]
src/test/ui/parser/issue-56031.stderr [new file with mode: 0644]
src/test/ui/pattern/issue-11577.rs [new file with mode: 0644]
src/test/ui/pattern/issue-15080.rs [new file with mode: 0644]
src/test/ui/pattern/issue-72574-2.rs [new file with mode: 0644]
src/test/ui/pattern/issue-72574-2.stderr [new file with mode: 0644]
src/test/ui/pattern/issue-8351-1.rs [new file with mode: 0644]
src/test/ui/pattern/issue-8351-2.rs [new file with mode: 0644]
src/test/ui/proc-macro/auxiliary/expand-expr.rs [new file with mode: 0644]
src/test/ui/proc-macro/auxiliary/included-file.txt [new file with mode: 0644]
src/test/ui/proc-macro/expand-expr.rs [new file with mode: 0644]
src/test/ui/proc-macro/expand-expr.stderr [new file with mode: 0644]
src/test/ui/proc-macro/issue-39889.rs
src/test/ui/process/issue-14456.rs [new file with mode: 0644]
src/test/ui/process/issue-16272.rs [new file with mode: 0644]
src/test/ui/process/issue-20091.rs [new file with mode: 0644]
src/test/ui/process/process-panic-after-fork.rs
src/test/ui/process/signal-exit-status.rs [new file with mode: 0644]
src/test/ui/reachable/expr_cast.rs
src/test/ui/reachable/expr_cast.stderr
src/test/ui/regions/issue-21520.rs [new file with mode: 0644]
src/test/ui/regions/issue-26448-1.rs [new file with mode: 0644]
src/test/ui/regions/issue-26448-2.rs [new file with mode: 0644]
src/test/ui/regions/issue-26448-3.rs [new file with mode: 0644]
src/test/ui/required-lang-item.rs [deleted file]
src/test/ui/required-lang-item.stderr [deleted file]
src/test/ui/resolve/editions-crate-root-2015.rs [new file with mode: 0644]
src/test/ui/resolve/editions-crate-root-2015.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-12796.rs [new file with mode: 0644]
src/test/ui/resolve/issue-12796.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-23716.rs [new file with mode: 0644]
src/test/ui/resolve/issue-23716.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-3021-c.rs [new file with mode: 0644]
src/test/ui/resolve/issue-3021-c.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-3021.rs [new file with mode: 0644]
src/test/ui/resolve/issue-3021.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-31845.rs [new file with mode: 0644]
src/test/ui/resolve/issue-31845.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-5099.rs [new file with mode: 0644]
src/test/ui/resolve/issue-5099.stderr [new file with mode: 0644]
src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs [new file with mode: 0644]
src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs
src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr [new file with mode: 0644]
src/test/ui/self/issue-61882-2.rs [new file with mode: 0644]
src/test/ui/self/issue-61882-2.stderr [new file with mode: 0644]
src/test/ui/self/issue-61882.rs [new file with mode: 0644]
src/test/ui/self/issue-61882.stderr [new file with mode: 0644]
src/test/ui/signal-exit-status.rs [deleted file]
src/test/ui/simd/intrinsic/generic-bitmask.rs
src/test/ui/simd/intrinsic/generic-bitmask.stderr
src/test/ui/simd/intrinsic/generic-select.rs
src/test/ui/simd/intrinsic/generic-select.stderr
src/test/ui/simd/libm_no_std_cant_float.rs [new file with mode: 0644]
src/test/ui/simd/libm_no_std_cant_float.stderr [new file with mode: 0644]
src/test/ui/simd/portable-intrinsics-arent-exposed.rs [new file with mode: 0644]
src/test/ui/simd/portable-intrinsics-arent-exposed.stderr [new file with mode: 0644]
src/test/ui/simd/simd-bitmask.rs [new file with mode: 0644]
src/test/ui/specialization/transmute-specialization.rs [new file with mode: 0644]
src/test/ui/specialization/transmute-specialization.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
src/test/ui/static/auxiliary/nested_item.rs [new file with mode: 0644]
src/test/ui/static/nested_item_main.rs [new file with mode: 0644]
src/test/ui/statics/issue-14227.mir.stderr [new file with mode: 0644]
src/test/ui/statics/issue-14227.rs [new file with mode: 0644]
src/test/ui/statics/issue-14227.thir.stderr [new file with mode: 0644]
src/test/ui/statics/uninhabited-static.rs
src/test/ui/statics/uninhabited-static.stderr
src/test/ui/structs-enums/issue-50731.rs [new file with mode: 0644]
src/test/ui/structs-enums/rec-align-u64.rs
src/test/ui/structured-compare.rs [deleted file]
src/test/ui/suggestions/boxed-variant-field.rs [new file with mode: 0644]
src/test/ui/suggestions/boxed-variant-field.stderr [new file with mode: 0644]
src/test/ui/suggestions/issue-71394-no-from-impl.stderr
src/test/ui/supported-cast.rs [deleted file]
src/test/ui/svh/auxiliary/changing-crates-a1.rs [new file with mode: 0644]
src/test/ui/svh/auxiliary/changing-crates-a2.rs [new file with mode: 0644]
src/test/ui/svh/auxiliary/changing-crates-b.rs [new file with mode: 0644]
src/test/ui/svh/changing-crates.rs [new file with mode: 0644]
src/test/ui/svh/changing-crates.stderr [new file with mode: 0644]
src/test/ui/syntax-trait-polarity.rs [deleted file]
src/test/ui/syntax-trait-polarity.stderr [deleted file]
src/test/ui/synthetic-param.stderr
src/test/ui/terminate-in-initializer.rs [deleted file]
src/test/ui/terr-sorts.stderr
src/test/ui/test-attrs/issue-20823.rs [new file with mode: 0644]
src/test/ui/thin-lto-global-allocator.rs [deleted file]
src/test/ui/thinlto/all-crates.rs [deleted file]
src/test/ui/thinlto/auxiliary/dylib.rs [deleted file]
src/test/ui/thinlto/auxiliary/msvc-imp-present.rs [deleted file]
src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs [deleted file]
src/test/ui/thinlto/dylib-works.rs [deleted file]
src/test/ui/thinlto/msvc-imp-present.rs [deleted file]
src/test/ui/thinlto/thin-lto-inlines.rs [deleted file]
src/test/ui/thinlto/thin-lto-inlines2.rs [deleted file]
src/test/ui/thinlto/weak-works.rs [deleted file]
src/test/ui/threads-sendsync/issue-24313.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/issue-4448.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/issue-8827.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/issue-9396.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/trivial-message.rs [new file with mode: 0644]
src/test/ui/threads-sendsync/yield2.rs [new file with mode: 0644]
src/test/ui/trace_macros-format.rs [deleted file]
src/test/ui/trace_macros-format.stderr [deleted file]
src/test/ui/traits/alias/issue-83613.stderr
src/test/ui/traits/issue-24010.rs [new file with mode: 0644]
src/test/ui/traits/issue-38604.rs [new file with mode: 0644]
src/test/ui/traits/issue-38604.stderr [new file with mode: 0644]
src/test/ui/traits/issue-3973.rs [new file with mode: 0644]
src/test/ui/traits/issue-3973.stderr [new file with mode: 0644]
src/test/ui/traits/issue-59029-1.rs [new file with mode: 0644]
src/test/ui/traits/issue-59029-1.stderr [new file with mode: 0644]
src/test/ui/traits/issue-72455.rs [new file with mode: 0644]
src/test/ui/traits/issue-78372.stderr
src/test/ui/traits/object-does-not-impl-trait.rs [new file with mode: 0644]
src/test/ui/traits/object-does-not-impl-trait.stderr [new file with mode: 0644]
src/test/ui/traits/syntax-trait-polarity.rs [new file with mode: 0644]
src/test/ui/traits/syntax-trait-polarity.stderr [new file with mode: 0644]
src/test/ui/transmute-specialization.rs [deleted file]
src/test/ui/transmute-specialization.stderr [deleted file]
src/test/ui/trivial-message.rs [deleted file]
src/test/ui/try-block/issue-45124.rs [new file with mode: 0644]
src/test/ui/try-macro-suggestion.rs [deleted file]
src/test/ui/try-macro-suggestion.stderr [deleted file]
src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs
src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs
src/test/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr
src/test/ui/type-alias-impl-trait/issue-60662.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-60662.stdout [new file with mode: 0644]
src/test/ui/type-inference/issue-30225.rs [new file with mode: 0644]
src/test/ui/type-inference/issue-30225.stderr [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs [new file with mode: 0644]
src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs [new file with mode: 0644]
src/test/ui/typeck/issue-43189.rs [new file with mode: 0644]
src/test/ui/typeck/issue-43189.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-46112.rs [new file with mode: 0644]
src/test/ui/typeck/issue-46112.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs [new file with mode: 0644]
src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs [new file with mode: 0644]
src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr [new file with mode: 0644]
src/test/ui/unary-minus-suffix-inference.rs [deleted file]
src/test/ui/unboxed-closures/issue-18652.rs [new file with mode: 0644]
src/test/ui/unnecessary-extern-crate.rs [deleted file]
src/test/ui/unnecessary-extern-crate.stderr [deleted file]
src/test/ui/unrestricted-attribute-tokens.rs [deleted file]
src/test/ui/unsized/issue-30355.rs [new file with mode: 0644]
src/test/ui/unsized/issue-30355.stderr [new file with mode: 0644]
src/test/ui/use/use-nested-groups-unused-imports.rs
src/test/ui/use/use-nested-groups-unused-imports.stderr
src/test/ui/warn-ctypes-inhibit.rs [deleted file]
src/test/ui/x86stdcall.rs
src/test/ui/yield2.rs [deleted file]
src/tools/cargo
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/excessive_bools.rs
src/tools/clippy/clippy_lints/src/future_not_send.rs
src/tools/clippy/clippy_lints/src/matches.rs
src/tools/clippy/clippy_lints/src/non_expressive_names.rs
src/tools/clippy/clippy_lints/src/write.rs
src/tools/clippy/clippy_utils/src/ast_utils.rs
src/tools/clippy/clippy_utils/src/higher.rs
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr
src/tools/clippy/tests/ui/deref_addrof.fixed
src/tools/clippy/tests/ui/deref_addrof.rs
src/tools/clippy/tests/ui/double_neg.rs
src/tools/clippy/tests/ui/double_neg.stderr
src/tools/clippy/tests/ui/fn_params_excessive_bools.rs
src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
src/tools/clippy/tests/ui/formatting.rs
src/tools/clippy/tests/ui/formatting.stderr
src/tools/clippy/tests/ui/literals.rs
src/tools/clippy/tests/ui/many_single_char_names.rs
src/tools/clippy/tests/ui/many_single_char_names.stderr
src/tools/clippy/tests/ui/mistyped_literal_suffix.fixed
src/tools/clippy/tests/ui/mistyped_literal_suffix.rs
src/tools/clippy/tests/ui/mistyped_literal_suffix.stderr
src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.stderr
src/tools/clippy/tests/ui/needless_continue.rs
src/tools/clippy/tests/ui/needless_continue.stderr
src/tools/clippy/tests/ui/non_expressive_names.rs
src/tools/clippy/tests/ui/non_expressive_names.stderr
src/tools/clippy/tests/ui/redundant_closure_call_early.rs
src/tools/clippy/tests/ui/redundant_else.rs
src/tools/clippy/tests/ui/similar_names.rs
src/tools/clippy/tests/ui/similar_names.stderr
src/tools/clippy/tests/ui/suspicious_else_formatting.rs
src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
src/tools/compiletest/src/util.rs
src/tools/html-checker/main.rs
src/tools/miri
src/tools/rust-analyzer
src/tools/rustdoc-js/tester.js
src/tools/rustfmt/.github/workflows/rustdoc_check.yml [new file with mode: 0644]
src/tools/rustfmt/Configurations.md
src/tools/rustfmt/Contributing.md
src/tools/rustfmt/README.md
src/tools/rustfmt/appveyor.yml [deleted file]
src/tools/rustfmt/intellij.md
src/tools/rustfmt/legacy-rustfmt.toml [deleted file]
src/tools/rustfmt/rust-toolchain
src/tools/rustfmt/src/attr.rs
src/tools/rustfmt/src/attr/doc_comment.rs
src/tools/rustfmt/src/bin/main.rs
src/tools/rustfmt/src/cargo-fmt/main.rs
src/tools/rustfmt/src/chains.rs
src/tools/rustfmt/src/comment.rs
src/tools/rustfmt/src/config/options.rs
src/tools/rustfmt/src/emitter/checkstyle.rs
src/tools/rustfmt/src/emitter/diff.rs
src/tools/rustfmt/src/expr.rs
src/tools/rustfmt/src/format-diff/main.rs
src/tools/rustfmt/src/formatting.rs
src/tools/rustfmt/src/git-rustfmt/main.rs
src/tools/rustfmt/src/imports.rs
src/tools/rustfmt/src/items.rs
src/tools/rustfmt/src/lib.rs
src/tools/rustfmt/src/lists.rs
src/tools/rustfmt/src/macros.rs
src/tools/rustfmt/src/matches.rs
src/tools/rustfmt/src/modules.rs
src/tools/rustfmt/src/overflow.rs
src/tools/rustfmt/src/pairs.rs
src/tools/rustfmt/src/patterns.rs
src/tools/rustfmt/src/reorder.rs
src/tools/rustfmt/src/syntux/parser.rs
src/tools/rustfmt/src/syntux/session.rs
src/tools/rustfmt/src/test/mod.rs
src/tools/rustfmt/src/test/mod_resolver.rs
src/tools/rustfmt/src/types.rs
src/tools/rustfmt/src/utils.rs
src/tools/rustfmt/src/visitor.rs
src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs [new file with mode: 0644]
src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs [new file with mode: 0644]
src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/configs/group_imports/One.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/empty-item-single-line-false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs
src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/configs/group_imports/One.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/empty-item-single-line-false.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/issue_4850.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs
src/tools/tidy/src/lib.rs
src/tools/tidy/src/ui_tests.rs

index 6f95dae42a4ab1a9edd126739aacfde5914fdcb8..7cd07e3847282b9d9405a5244414c2f49283adc8 100644 (file)
@@ -888,9 +888,9 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaa3b8db7f3341ddef15786d250106334d4a6c4b0ae4a46cd77082777d9849b9"
+checksum = "877cc2f9b8367e32b6dabb9d581557e651cb3aa693a37f8679091bbf42687d5d"
 dependencies = [
  "curl-sys",
  "libc",
@@ -903,9 +903,9 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.49+curl-7.79.1"
+version = "0.4.50+curl-7.79.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0f44960aea24a786a46907b8824ebc0e66ca06bf4e4978408c7499620343483"
+checksum = "4856b76919dd599f31236bb18db5f5bd36e2ce131e64f857ca5c259665b76171"
 dependencies = [
  "cc",
  "libc",
index e2424e7d7ad9064f38563795d6ce59f54cba963f..abfe8360987c868bbc696928ec38eb92ea60b7bc 100644 (file)
@@ -2058,7 +2058,7 @@ pub struct InlineAsm {
     pub template: Vec<InlineAsmTemplatePiece>,
     pub template_strs: Box<[(Symbol, Option<Symbol>, Span)]>,
     pub operands: Vec<(InlineAsmOperand, Span)>,
-    pub clobber_abi: Option<(Symbol, Span)>,
+    pub clobber_abis: Vec<(Symbol, Span)>,
     pub options: InlineAsmOptions,
     pub line_spans: Vec<Span>,
 }
@@ -2645,34 +2645,42 @@ fn default() -> FnHeader {
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TraitKind(
-    pub IsAuto,
-    pub Unsafe,
-    pub Generics,
-    pub GenericBounds,
-    pub Vec<P<AssocItem>>,
-);
+pub struct Trait {
+    pub unsafety: Unsafe,
+    pub is_auto: IsAuto,
+    pub generics: Generics,
+    pub bounds: GenericBounds,
+    pub items: Vec<P<AssocItem>>,
+}
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TyAliasKind(pub Defaultness, pub Generics, pub GenericBounds, pub Option<P<Ty>>);
+pub struct TyAlias {
+    pub defaultness: Defaultness,
+    pub generics: Generics,
+    pub bounds: GenericBounds,
+    pub ty: Option<P<Ty>>,
+}
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct ImplKind {
-    pub unsafety: Unsafe,
-    pub polarity: ImplPolarity,
+pub struct Impl {
     pub defaultness: Defaultness,
-    pub constness: Const,
+    pub unsafety: Unsafe,
     pub generics: Generics,
-
+    pub constness: Const,
+    pub polarity: ImplPolarity,
     /// The trait being implemented, if any.
     pub of_trait: Option<TraitRef>,
-
     pub self_ty: P<Ty>,
     pub items: Vec<P<AssocItem>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
-pub struct FnKind(pub Defaultness, pub FnSig, pub Generics, pub Option<P<Block>>);
+pub struct Fn {
+    pub defaultness: Defaultness,
+    pub generics: Generics,
+    pub sig: FnSig,
+    pub body: Option<P<Block>>,
+}
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ItemKind {
@@ -2695,7 +2703,7 @@ pub enum ItemKind {
     /// A function declaration (`fn`).
     ///
     /// E.g., `fn foo(bar: usize) -> usize { .. }`.
-    Fn(Box<FnKind>),
+    Fn(Box<Fn>),
     /// A module declaration (`mod`).
     ///
     /// E.g., `mod foo;` or `mod foo { .. }`.
@@ -2707,11 +2715,11 @@ pub enum ItemKind {
     /// E.g., `extern {}` or `extern "C" {}`.
     ForeignMod(ForeignMod),
     /// Module-level inline assembly (from `global_asm!()`).
-    GlobalAsm(InlineAsm),
+    GlobalAsm(Box<InlineAsm>),
     /// A type alias (`type`).
     ///
     /// E.g., `type Foo = Bar<u8>;`.
-    TyAlias(Box<TyAliasKind>),
+    TyAlias(Box<TyAlias>),
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
@@ -2727,7 +2735,7 @@ pub enum ItemKind {
     /// A trait declaration (`trait`).
     ///
     /// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
-    Trait(Box<TraitKind>),
+    Trait(Box<Trait>),
     /// Trait alias
     ///
     /// E.g., `trait Foo = Bar + Quux;`.
@@ -2735,7 +2743,7 @@ pub enum ItemKind {
     /// An implementation.
     ///
     /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
-    Impl(Box<ImplKind>),
+    Impl(Box<Impl>),
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
@@ -2782,14 +2790,14 @@ pub fn descr(&self) -> &str {
 
     pub fn generics(&self) -> Option<&Generics> {
         match self {
-            Self::Fn(box FnKind(_, _, generics, _))
-            | Self::TyAlias(box TyAliasKind(_, generics, ..))
+            Self::Fn(box Fn { generics, .. })
+            | Self::TyAlias(box TyAlias { generics, .. })
             | Self::Enum(_, generics)
             | Self::Struct(_, generics)
             | Self::Union(_, generics)
-            | Self::Trait(box TraitKind(_, _, generics, ..))
+            | Self::Trait(box Trait { generics, .. })
             | Self::TraitAlias(generics, _)
-            | Self::Impl(box ImplKind { generics, .. }) => Some(generics),
+            | Self::Impl(box Impl { generics, .. }) => Some(generics),
             _ => None,
         }
     }
@@ -2812,9 +2820,9 @@ pub enum AssocItemKind {
     /// If `def` is parsed, then the constant is provided, and otherwise required.
     Const(Defaultness, P<Ty>, Option<P<Expr>>),
     /// An associated function.
-    Fn(Box<FnKind>),
+    Fn(Box<Fn>),
     /// An associated type.
-    TyAlias(Box<TyAliasKind>),
+    TyAlias(Box<TyAlias>),
     /// A macro expanding to associated items.
     MacCall(MacCall),
 }
@@ -2825,9 +2833,9 @@ pub enum AssocItemKind {
 impl AssocItemKind {
     pub fn defaultness(&self) -> Defaultness {
         match *self {
-            Self::Const(def, ..)
-            | Self::Fn(box FnKind(def, ..))
-            | Self::TyAlias(box TyAliasKind(def, ..)) => def,
+            Self::Const(defaultness, ..)
+            | Self::Fn(box Fn { defaultness, .. })
+            | Self::TyAlias(box TyAlias { defaultness, .. }) => defaultness,
             Self::MacCall(..) => Defaultness::Final,
         }
     }
@@ -2864,9 +2872,9 @@ pub enum ForeignItemKind {
     /// A foreign static item (`static FOO: u8`).
     Static(P<Ty>, Mutability, Option<P<Expr>>),
     /// An foreign function.
-    Fn(Box<FnKind>),
+    Fn(Box<Fn>),
     /// An foreign type.
-    TyAlias(Box<TyAliasKind>),
+    TyAlias(Box<TyAlias>),
     /// A macro expanding to foreign items.
     MacCall(MacCall),
 }
index 74def2bab1bfa2a58319e728f6765a2c9dc0f081..fc5cc963992579b76514eeddb92d9fb0a851b3b3 100644 (file)
@@ -459,7 +459,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             vis.visit_mt(mt);
         }
         TyKind::BareFn(bft) => {
-            let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut();
+            let BareFnTy { unsafety, ext: _, generic_params, decl } = bft.deref_mut();
+            visit_unsafety(unsafety, vis);
             generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
             vis.visit_fn_decl(decl);
         }
@@ -488,7 +489,8 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
 }
 
 pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: &mut T) {
-    let ForeignMod { unsafety: _, abi: _, items } = foreign_mod;
+    let ForeignMod { unsafety, abi: _, items } = foreign_mod;
+    visit_unsafety(unsafety, vis);
     items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
 }
 
@@ -788,6 +790,38 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut
     }
 }
 
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T) {
+    match defaultness {
+        Defaultness::Default(span) => vis.visit_span(span),
+        Defaultness::Final => {}
+    }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_unsafety<T: MutVisitor>(unsafety: &mut Unsafe, vis: &mut T) {
+    match unsafety {
+        Unsafe::Yes(span) => vis.visit_span(span),
+        Unsafe::No => {}
+    }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_polarity<T: MutVisitor>(polarity: &mut ImplPolarity, vis: &mut T) {
+    match polarity {
+        ImplPolarity::Positive => {}
+        ImplPolarity::Negative(span) => vis.visit_span(span),
+    }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_constness<T: MutVisitor>(constness: &mut Const, vis: &mut T) {
+    match constness {
+        Const::Yes(span) => vis.visit_span(span),
+        Const::No => {}
+    }
+}
+
 pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut Async, vis: &mut T) {
     match asyncness {
         Async::Yes { span: _, closure_id, return_impl_trait_id } => {
@@ -955,25 +989,35 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
     match kind {
         ItemKind::ExternCrate(_orig_name) => {}
         ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
-        ItemKind::Static(ty, _, expr) | ItemKind::Const(_, ty, expr) => {
+        ItemKind::Static(ty, _, expr) => {
             vis.visit_ty(ty);
             visit_opt(expr, |expr| vis.visit_expr(expr));
         }
-        ItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        ItemKind::Const(defaultness, ty, expr) => {
+            visit_defaultness(defaultness, vis);
+            vis.visit_ty(ty);
+            visit_opt(expr, |expr| vis.visit_expr(expr));
+        }
+        ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            visit_defaultness(defaultness, vis);
             visit_fn_sig(sig, vis);
             vis.visit_generics(generics);
             visit_opt(body, |body| vis.visit_block(body));
         }
-        ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
-            ModKind::Loaded(items, _inline, inner_span) => {
-                vis.visit_span(inner_span);
-                items.flat_map_in_place(|item| vis.flat_map_item(item));
+        ItemKind::Mod(unsafety, mod_kind) => {
+            visit_unsafety(unsafety, vis);
+            match mod_kind {
+                ModKind::Loaded(items, _inline, inner_span) => {
+                    vis.visit_span(inner_span);
+                    items.flat_map_in_place(|item| vis.flat_map_item(item));
+                }
+                ModKind::Unloaded => {}
             }
-            ModKind::Unloaded => {}
-        },
+        }
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
         ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
-        ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        ItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+            visit_defaultness(defaultness, vis);
             vis.visit_generics(generics);
             visit_bounds(bounds, vis);
             visit_opt(ty, |ty| vis.visit_ty(ty));
@@ -986,22 +1030,27 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
             vis.visit_variant_data(variant_data);
             vis.visit_generics(generics);
         }
-        ItemKind::Impl(box ImplKind {
-            unsafety: _,
-            polarity: _,
-            defaultness: _,
-            constness: _,
+        ItemKind::Impl(box Impl {
+            defaultness,
+            unsafety,
             generics,
+            constness,
+            polarity,
             of_trait,
             self_ty,
             items,
         }) => {
+            visit_defaultness(defaultness, vis);
+            visit_unsafety(unsafety, vis);
             vis.visit_generics(generics);
+            visit_constness(constness, vis);
+            visit_polarity(polarity, vis);
             visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
             vis.visit_ty(self_ty);
             items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
         }
-        ItemKind::Trait(box TraitKind(.., generics, bounds, items)) => {
+        ItemKind::Trait(box Trait { unsafety, is_auto: _, generics, bounds, items }) => {
+            visit_unsafety(unsafety, vis);
             vis.visit_generics(generics);
             visit_bounds(bounds, vis);
             items.flat_map_in_place(|item| vis.flat_map_trait_item(item));
@@ -1025,16 +1074,19 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
     visitor.visit_vis(vis);
     visit_attrs(attrs, visitor);
     match kind {
-        AssocItemKind::Const(_, ty, expr) => {
+        AssocItemKind::Const(defaultness, ty, expr) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_ty(ty);
             visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
-        AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        AssocItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1047,8 +1099,10 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
 }
 
 pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
-    let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header;
+    let FnHeader { unsafety, asyncness, constness, ext: _ } = header;
+    visit_constness(constness, vis);
     vis.visit_asyncness(asyncness);
+    visit_unsafety(unsafety, vis);
 }
 
 // FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
@@ -1114,12 +1168,14 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
             visitor.visit_ty(ty);
             visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
-        ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+            visit_defaultness(defaultness, visitor);
             visitor.visit_generics(generics);
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
index 542a330a031414f469f52a256793b93c311f1fc7..80a06fa594366de0492471300308e7ab4048e02d 100644 (file)
@@ -38,7 +38,7 @@ fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
             i += 1;
         }
         // like the first, a last line of all stars should be omitted
-        if j > i && lines[j - 1].chars().skip(1).all(|c| c == '*') {
+        if j > i && !lines[j - 1].is_empty() && lines[j - 1].chars().all(|c| c == '*') {
             j -= 1;
         }
 
@@ -169,7 +169,7 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme
                 if let Some(mut idx) = token_text.find('\n') {
                     code_to_the_left = false;
                     while let Some(next_newline) = &token_text[idx + 1..].find('\n') {
-                        idx = idx + 1 + next_newline;
+                        idx += 1 + next_newline;
                         comments.push(Comment {
                             style: CommentStyle::BlankLine,
                             lines: vec![],
index 500c97e65ef9cc868611037369912944f783430a..742a7d1d2df70907fa087b4221fffbf816b835bf 100644 (file)
@@ -212,7 +212,8 @@ pub fn to_ast_binop(&self) -> Option<BinOpKind> {
     /// parentheses while having a high degree of confidence on the correctness of the suggestion.
     pub fn can_continue_expr_unambiguously(&self) -> bool {
         use AssocOp::*;
-        match self {
+        matches!(
+            self,
             BitXor | // `{ 42 } ^ 3`
             Assign | // `{ 42 } = { 42 }`
             Divide | // `{ 42 } / 42`
@@ -225,9 +226,8 @@ pub fn can_continue_expr_unambiguously(&self) -> bool {
             As | // `{ 42 } as usize`
             // Equal | // `{ 42 } == { 42 }`    Accepting these here would regress incorrect
             // NotEqual | // `{ 42 } != { 42 }  struct literals parser recovery.
-            Colon => true, // `{ 42 }: usize`
-            _ => false,
-        }
+            Colon, // `{ 42 }: usize`
+        )
     }
 }
 
index b38031042e0f09ed1265acf60725eca661dc84f5..be794ed221ae702331d0940d0df935545d255b61 100644 (file)
@@ -285,7 +285,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_ty(typ);
             walk_list!(visitor, visit_expr, expr);
         }
-        ItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) => {
+        ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
             visitor.visit_fn(kind, item.span, item.id)
@@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
-        ItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty)) => {
+        ItemKind::TyAlias(box TyAlias { defaultness: _, ref generics, ref bounds, ref ty }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
@@ -309,12 +309,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
         }
-        ItemKind::Impl(box ImplKind {
-            unsafety: _,
-            polarity: _,
+        ItemKind::Impl(box Impl {
             defaultness: _,
-            constness: _,
+            unsafety: _,
             ref generics,
+            constness: _,
+            polarity: _,
             ref of_trait,
             ref self_ty,
             ref items,
@@ -329,7 +329,13 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             visitor.visit_variant_data(struct_definition);
         }
-        ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref items)) => {
+        ItemKind::Trait(box Trait {
+            unsafety: _,
+            is_auto: _,
+            ref generics,
+            ref bounds,
+            ref items,
+        }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
@@ -547,12 +553,12 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
-        ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
-        ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        ForeignItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
@@ -653,12 +659,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
-        AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+        AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
-        AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+        AssocItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
index d0da88f1cc095163e82ebef41dd2df9a95eea2e3..cfa97ff84ec498910e0e1a9fea3dd8e716967274 100644 (file)
@@ -2,9 +2,11 @@
 
 use rustc_ast::*;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_span::{Span, Symbol};
+use rustc_session::parse::feature_err;
+use rustc_span::{sym, Span, Symbol};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
 use std::fmt::Write;
@@ -18,6 +20,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             struct_span_err!(self.sess, sp, E0472, "inline assembly is unsupported on this target")
                 .emit();
         }
+        if let Some(asm_arch) = asm_arch {
+            // Inline assembly is currently only stable for these architectures.
+            let is_stable = matches!(
+                asm_arch,
+                asm::InlineAsmArch::X86
+                    | asm::InlineAsmArch::X86_64
+                    | asm::InlineAsmArch::Arm
+                    | asm::InlineAsmArch::AArch64
+                    | asm::InlineAsmArch::RiscV32
+                    | asm::InlineAsmArch::RiscV64
+            );
+            if !is_stable && !self.sess.features_untracked().asm_experimental_arch {
+                feature_err(
+                    &self.sess.parse_sess,
+                    sym::asm_experimental_arch,
+                    sp,
+                    "inline assembly is not stable yet on this architecture",
+                )
+                .emit();
+            }
+        }
         if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
             && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
             && !self.sess.opts.actually_rustdoc
@@ -27,22 +50,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 .emit();
         }
 
-        let mut clobber_abi = None;
+        let mut clobber_abis = FxHashMap::default();
         if let Some(asm_arch) = asm_arch {
-            if let Some((abi_name, abi_span)) = asm.clobber_abi {
-                match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, abi_name) {
-                    Ok(abi) => clobber_abi = Some((abi, abi_span)),
+            for (abi_name, abi_span) in &asm.clobber_abis {
+                match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) {
+                    Ok(abi) => {
+                        // If the abi was already in the list, emit an error
+                        match clobber_abis.get(&abi) {
+                            Some((prev_name, prev_sp)) => {
+                                let mut err = self.sess.struct_span_err(
+                                    *abi_span,
+                                    &format!("`{}` ABI specified multiple times", prev_name),
+                                );
+                                err.span_label(*prev_sp, "previously specified here");
+
+                                // Multiple different abi names may actually be the same ABI
+                                // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI
+                                let source_map = self.sess.source_map();
+                                if source_map.span_to_snippet(*prev_sp)
+                                    != source_map.span_to_snippet(*abi_span)
+                                {
+                                    err.note("these ABIs are equivalent on the current target");
+                                }
+
+                                err.emit();
+                            }
+                            None => {
+                                clobber_abis.insert(abi, (abi_name, *abi_span));
+                            }
+                        }
+                    }
                     Err(&[]) => {
                         self.sess
                             .struct_span_err(
-                                abi_span,
+                                *abi_span,
                                 "`clobber_abi` is not supported on this target",
                             )
                             .emit();
                     }
                     Err(supported_abis) => {
                         let mut err =
-                            self.sess.struct_span_err(abi_span, "invalid ABI for `clobber_abi`");
+                            self.sess.struct_span_err(*abi_span, "invalid ABI for `clobber_abi`");
                         let mut abis = format!("`{}`", supported_abis[0]);
                         for m in &supported_abis[1..] {
                             let _ = write!(abis, ", `{}`", m);
@@ -121,10 +169,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
                         }
                     }
-                    InlineAsmOperand::Const { ref anon_const } => hir::InlineAsmOperand::Const {
-                        anon_const: self.lower_anon_const(anon_const),
-                    },
+                    InlineAsmOperand::Const { ref anon_const } => {
+                        if !self.sess.features_untracked().asm_const {
+                            feature_err(
+                                &self.sess.parse_sess,
+                                sym::asm_const,
+                                *op_sp,
+                                "const operands for inline assembly are unstable",
+                            )
+                            .emit();
+                        }
+                        hir::InlineAsmOperand::Const {
+                            anon_const: self.lower_anon_const(anon_const),
+                        }
+                    }
                     InlineAsmOperand::Sym { ref expr } => {
+                        if !self.sess.features_untracked().asm_sym {
+                            feature_err(
+                                &self.sess.parse_sess,
+                                sym::asm_sym,
+                                *op_sp,
+                                "sym operands for inline assembly are unstable",
+                            )
+                            .emit();
+                        }
                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
                     }
                 };
@@ -306,8 +374,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         // If a clobber_abi is specified, add the necessary clobbers to the
         // operands list.
-        if let Some((abi, abi_span)) = clobber_abi {
+        let mut clobbered = FxHashSet::default();
+        for (abi, (_, abi_span)) in clobber_abis {
             for &clobber in abi.clobbered_regs() {
+                // Don't emit a clobber for a register already clobbered
+                if clobbered.contains(&clobber) {
+                    continue;
+                }
+
                 let mut output_used = false;
                 clobber.overlapping_regs(|reg| {
                     if used_output_regs.contains_key(&reg) {
@@ -324,6 +398,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         },
                         self.lower_span(abi_span),
                     ));
+                    clobbered.insert(clobber);
                 }
             }
         }
index 63b20cd320b37b60ef04f67f0acd4b81f1c79625..6a4571cf6d278928ab4bd8ae10ceda56613f7e56 100644 (file)
@@ -49,7 +49,7 @@ fn visit_item(&mut self, item: &'a Item) {
         self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
             let this = &mut ItemLowerer { lctx: this };
             match item.kind {
-                ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
+                ItemKind::Impl(box Impl { ref of_trait, .. }) => {
                     this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
                 }
                 _ => visit::walk_item(this, item),
@@ -218,12 +218,12 @@ fn lower_item_kind(
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
                 hir::ItemKind::Const(ty, body_id)
             }
-            ItemKind::Fn(box FnKind(
-                _,
-                FnSig { ref decl, header, span: fn_sig_span },
+            ItemKind::Fn(box Fn {
+                sig: FnSig { ref decl, header, span: fn_sig_span },
                 ref generics,
                 ref body,
-            )) => {
+                ..
+            }) => {
                 let fn_def_id = self.resolver.local_def_id(id);
                 self.with_new_scopes(|this| {
                     this.current_item = Some(ident.span);
@@ -273,7 +273,7 @@ fn lower_item_kind(
             ItemKind::GlobalAsm(ref asm) => {
                 hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
             }
-            ItemKind::TyAlias(box TyAliasKind(_, ref gen, _, Some(ref ty))) => {
+            ItemKind::TyAlias(box TyAlias { ref generics, ty: Some(ref ty), .. }) => {
                 // We lower
                 //
                 // type Foo = impl Trait
@@ -288,10 +288,10 @@ fn lower_item_kind(
                         capturable_lifetimes: &mut FxHashSet::default(),
                     },
                 );
-                let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
+                let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 hir::ItemKind::TyAlias(ty, generics)
             }
-            ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, None)) => {
+            ItemKind::TyAlias(box TyAlias { ref generics, ty: None, .. }) => {
                 let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 hir::ItemKind::TyAlias(ty, generics)
@@ -318,7 +318,7 @@ fn lower_item_kind(
                     self.lower_generics(generics, ImplTraitContext::disallowed()),
                 )
             }
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -384,13 +384,13 @@ fn lower_item_kind(
                     items: new_impl_items,
                 })
             }
-            ItemKind::Trait(box TraitKind(
+            ItemKind::Trait(box Trait {
                 is_auto,
                 unsafety,
                 ref generics,
                 ref bounds,
                 ref items,
-            )) => {
+            }) => {
                 let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
                 let items = self
                     .arena
@@ -655,7 +655,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir
             def_id,
             ident: self.lower_ident(i.ident),
             kind: match i.kind {
-                ForeignItemKind::Fn(box FnKind(_, ref sig, ref generics, _)) => {
+                ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
                     let fdec = &sig.decl;
                     let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
                         generics,
@@ -772,13 +772,13 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
                 let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
                 (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
             }
-            AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, None)) => {
+            AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
             }
-            AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, Some(ref body))) => {
+            AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
                 let asyncness = sig.header.asyncness;
                 let body_id =
                     self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
@@ -791,8 +791,8 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
-            AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref default)) => {
-                let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
+            AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
+                let ty = ty.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 let kind = hir::TraitItemKind::Type(
                     self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
@@ -818,11 +818,11 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         let (kind, has_default) = match &i.kind {
             AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()),
-            AssocItemKind::TyAlias(box TyAliasKind(_, _, _, default)) => {
-                (hir::AssocItemKind::Type, default.is_some())
+            AssocItemKind::TyAlias(box TyAlias { ty, .. }) => {
+                (hir::AssocItemKind::Type, ty.is_some())
             }
-            AssocItemKind::Fn(box FnKind(_, sig, _, default)) => {
-                (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, default.is_some())
+            AssocItemKind::Fn(box Fn { sig, body, .. }) => {
+                (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, body.is_some())
             }
             AssocItemKind::MacCall(..) => unimplemented!(),
         };
@@ -853,7 +853,7 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
                     hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
                 )
             }
-            AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+            AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
                 self.current_item = Some(i.span);
                 let asyncness = sig.header.asyncness;
                 let body_id =
@@ -869,7 +869,7 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
             }
-            AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, ty)) => {
+            AssocItemKind::TyAlias(box TyAlias { generics, ty, .. }) => {
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 let kind = match ty {
                     None => {
@@ -920,7 +920,7 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
             kind: match &i.kind {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
                 AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
-                AssocItemKind::Fn(box FnKind(_, sig, ..)) => {
+                AssocItemKind::Fn(box Fn { sig, .. }) => {
                     hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
                 }
                 AssocItemKind::MacCall(..) => unimplemented!(),
index 793f6504be6f79f030ea168db247a9a4793f1d80..1822ba6ec996493d952d217a25fa39253c5c383a 100644 (file)
@@ -1064,7 +1064,7 @@ fn visit_item(&mut self, item: &'a Item) {
         }
 
         match item.kind {
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 unsafety,
                 polarity,
                 defaultness: _,
@@ -1111,7 +1111,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 });
                 return; // Avoid visiting again.
             }
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -1152,8 +1152,8 @@ fn visit_item(&mut self, item: &'a Item) {
                         .emit();
                 }
             }
-            ItemKind::Fn(box FnKind(def, ref sig, ref generics, ref body)) => {
-                self.check_defaultness(item.span, def);
+            ItemKind::Fn(box Fn { defaultness, ref sig, ref generics, ref body }) => {
+                self.check_defaultness(item.span, defaultness);
 
                 if body.is_none() {
                     let msg = "free function without a body";
@@ -1195,19 +1195,13 @@ fn visit_item(&mut self, item: &'a Item) {
                     }
                 }
             }
-            ItemKind::Trait(box TraitKind(
-                is_auto,
-                _,
-                ref generics,
-                ref bounds,
-                ref trait_items,
-            )) => {
+            ItemKind::Trait(box Trait { is_auto, ref generics, ref bounds, ref items, .. }) => {
                 if is_auto == IsAuto::Yes {
                     // Auto traits cannot have generics, super traits nor contain items.
                     self.deny_generic_params(generics, item.ident.span);
                     self.deny_super_traits(bounds, item.ident.span);
                     self.deny_where_clause(&generics.where_clause, item.ident.span);
-                    self.deny_items(trait_items, item.ident.span);
+                    self.deny_items(items, item.ident.span);
                 }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
 
@@ -1217,7 +1211,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 self.visit_ident(item.ident);
                 self.visit_generics(generics);
                 self.with_banned_tilde_const(|this| walk_list!(this, visit_param_bound, bounds));
-                walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
+                walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return;
             }
@@ -1278,9 +1272,9 @@ fn visit_item(&mut self, item: &'a Item) {
                 let msg = "free static item without body";
                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
             }
-            ItemKind::TyAlias(box TyAliasKind(def, _, ref bounds, ref body)) => {
-                self.check_defaultness(item.span, def);
-                if body.is_none() {
+            ItemKind::TyAlias(box TyAlias { defaultness, ref bounds, ref ty, .. }) => {
+                self.check_defaultness(item.span, defaultness);
+                if ty.is_none() {
                     let msg = "free type alias without body";
                     self.error_item_without_body(item.span, "type", msg, " = <type>;");
                 }
@@ -1294,15 +1288,15 @@ fn visit_item(&mut self, item: &'a Item) {
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match &fi.kind {
-            ForeignItemKind::Fn(box FnKind(def, sig, _, body)) => {
-                self.check_defaultness(fi.span, *def);
+            ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
+                self.check_defaultness(fi.span, *defaultness);
                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
                 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
                 self.check_foreign_item_ascii_only(fi.ident);
             }
-            ForeignItemKind::TyAlias(box TyAliasKind(def, generics, bounds, body)) => {
-                self.check_defaultness(fi.span, *def);
-                self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
+            ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty, .. }) => {
+                self.check_defaultness(fi.span, *defaultness);
+                self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
                 self.check_type_no_bounds(bounds, "`extern` blocks");
                 self.check_foreign_ty_genericless(generics);
                 self.check_foreign_item_ascii_only(fi.ident);
@@ -1587,11 +1581,11 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                 AssocItemKind::Const(_, _, body) => {
                     self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
                 }
-                AssocItemKind::Fn(box FnKind(_, _, _, body)) => {
+                AssocItemKind::Fn(box Fn { body, .. }) => {
                     self.check_impl_item_provided(item.span, body, "function", " { <body> }");
                 }
-                AssocItemKind::TyAlias(box TyAliasKind(_, _, bounds, body)) => {
-                    self.check_impl_item_provided(item.span, body, "type", " = <type>;");
+                AssocItemKind::TyAlias(box TyAlias { bounds, ty, .. }) => {
+                    self.check_impl_item_provided(item.span, ty, "type", " = <type>;");
                     self.check_type_no_bounds(bounds, "`impl`s");
                 }
                 _ => {}
@@ -1600,7 +1594,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
 
         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
             self.invalid_visibility(&item.vis, None);
-            if let AssocItemKind::Fn(box FnKind(_, sig, _, _)) = &item.kind {
+            if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
                 self.check_trait_fn_not_const(sig.header.constness);
                 self.check_trait_fn_not_async(item.span, sig.header.asyncness);
             }
@@ -1611,7 +1605,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
         }
 
         match item.kind {
-            AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty))
+            AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. })
                 if ctxt == AssocCtxt::Trait =>
             {
                 self.visit_vis(&item.vis);
@@ -1623,7 +1617,7 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                 });
                 walk_list!(self, visit_ty, ty);
             }
-            AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
+            AssocItemKind::Fn(box Fn { ref sig, ref generics, ref body, .. })
                 if self.in_const_trait_impl
                     || ctxt == AssocCtxt::Trait
                     || matches!(sig.header.constness, Const::Yes(_)) =>
index 91b4597a9bb1f021357f9bfff3aada7bcee74ff0..b011a2e8117af32bad24e55ed9bdb9082016a9f6 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
 use rustc_ast::{PatKind, RangeEnd, VariantData};
 use rustc_errors::struct_span_err;
-use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
+use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_feature::{Features, GateIssue};
 use rustc_session::parse::{feature_err, feature_err_issue};
 use rustc_session::Session;
@@ -301,11 +301,14 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
 
 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
-        let attr_info =
-            attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
+        let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
         // Check feature gates for built-in attributes.
-        if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info {
-            gate_feature_fn!(self, has_feature, attr.span, name, descr);
+        if let Some(BuiltinAttribute {
+            gate: AttributeGate::Gated(_, name, descr, has_feature),
+            ..
+        }) = attr_info
+        {
+            gate_feature_fn!(self, has_feature, attr.span, *name, descr);
         }
         // Check unstable flavors of the `#[doc]` attribute.
         if attr.has_name(sym::doc) {
@@ -423,9 +426,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
-            ast::ItemKind::Impl(box ast::ImplKind {
-                polarity, defaultness, ref of_trait, ..
-            }) => {
+            ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
                 if let ast::ImplPolarity::Negative(span) = polarity {
                     gate_feature_post!(
                         &self,
@@ -441,7 +442,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
-            ast::ItemKind::Trait(box ast::TraitKind(ast::IsAuto::Yes, ..)) => {
+            ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
                 gate_feature_post!(
                     &self,
                     auto_traits,
@@ -459,7 +460,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
 
-            ast::ItemKind::TyAlias(box ast::TyAliasKind(_, _, _, Some(ref ty))) => {
+            ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ref ty), .. }) => {
                 self.check_impl_trait(&ty)
             }
 
@@ -541,15 +542,13 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
             ast::ExprKind::TryBlock(_) => {
                 gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
             }
-            ast::ExprKind::Block(_, opt_label) => {
-                if let Some(label) = opt_label {
-                    gate_feature_post!(
-                        &self,
-                        label_break_value,
-                        label.ident.span,
-                        "labels on blocks are unstable"
-                    );
-                }
+            ast::ExprKind::Block(_, Some(label)) => {
+                gate_feature_post!(
+                    &self,
+                    label_break_value,
+                    label.ident.span,
+                    "labels on blocks are unstable"
+                );
             }
             _ => {}
         }
@@ -634,7 +633,7 @@ fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
     fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
         let is_fn = match i.kind {
             ast::AssocItemKind::Fn(_) => true,
-            ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => {
+            ast::AssocItemKind::TyAlias(box ast::TyAlias { ref generics, ref ty, .. }) => {
                 if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
                     gate_feature_post!(
                         &self,
index 6d0589b7ba1af7a5ae205dc8a45df5f09ae9257e..f1f2387866d0d3d71afbcc6807919d9df11ec6a5 100644 (file)
@@ -1044,15 +1044,27 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
-            ast::ForeignItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
-                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+            ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
+                self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
             }
             ast::ForeignItemKind::Static(ty, mutbl, body) => {
                 let def = ast::Defaultness::Final;
                 self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
             }
-            ast::ForeignItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+            ast::ForeignItemKind::TyAlias(box ast::TyAlias {
+                defaultness,
+                generics,
+                bounds,
+                ty,
+            }) => {
+                self.print_associated_type(
+                    ident,
+                    generics,
+                    bounds,
+                    ty.as_deref(),
+                    vis,
+                    *defaultness,
+                );
             }
             ast::ForeignItemKind::MacCall(m) => {
                 self.print_mac(m);
@@ -1156,9 +1168,17 @@ fn print_associated_type(
             ast::ItemKind::Const(def, ref ty, ref body) => {
                 self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
             }
-            ast::ItemKind::Fn(box ast::FnKind(def, ref sig, ref gen, ref body)) => {
+            ast::ItemKind::Fn(box ast::Fn { defaultness, ref sig, ref generics, ref body }) => {
                 let body = body.as_deref();
-                self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
+                self.print_fn_full(
+                    sig,
+                    item.ident,
+                    generics,
+                    &item.vis,
+                    defaultness,
+                    body,
+                    &item.attrs,
+                );
             }
             ast::ItemKind::Mod(unsafety, ref mod_kind) => {
                 self.head(self.to_string(|s| {
@@ -1203,9 +1223,21 @@ fn print_associated_type(
                 self.print_inline_asm(asm);
                 self.end();
             }
-            ast::ItemKind::TyAlias(box ast::TyAliasKind(def, ref generics, ref bounds, ref ty)) => {
+            ast::ItemKind::TyAlias(box ast::TyAlias {
+                defaultness,
+                ref generics,
+                ref bounds,
+                ref ty,
+            }) => {
                 let ty = ty.as_deref();
-                self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
+                self.print_associated_type(
+                    item.ident,
+                    generics,
+                    bounds,
+                    ty,
+                    &item.vis,
+                    defaultness,
+                );
             }
             ast::ItemKind::Enum(ref enum_definition, ref params) => {
                 self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
@@ -1218,7 +1250,7 @@ fn print_associated_type(
                 self.head(visibility_qualified(&item.vis, "union"));
                 self.print_struct(struct_def, generics, item.ident, item.span, true);
             }
-            ast::ItemKind::Impl(box ast::ImplKind {
+            ast::ItemKind::Impl(box ast::Impl {
                 unsafety,
                 polarity,
                 defaultness,
@@ -1261,13 +1293,14 @@ fn print_associated_type(
                 }
                 self.bclose(item.span);
             }
-            ast::ItemKind::Trait(box ast::TraitKind(
+            ast::ItemKind::Trait(box ast::Trait {
                 is_auto,
                 unsafety,
                 ref generics,
                 ref bounds,
-                ref trait_items,
-            )) => {
+                ref items,
+                ..
+            }) => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_unsafety(unsafety);
@@ -1290,7 +1323,7 @@ fn print_associated_type(
                 self.s.word(" ");
                 self.bopen();
                 self.print_inner_attributes(&item.attrs);
-                for trait_item in trait_items {
+                for trait_item in items {
                     self.print_assoc_item(trait_item);
                 }
                 self.bclose(item.span);
@@ -1405,11 +1438,7 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
         }
     }
 
-    crate fn print_record_struct_body(
-        &mut self,
-        fields: &Vec<ast::FieldDef>,
-        span: rustc_span::Span,
-    ) {
+    crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
         self.nbsp();
         self.bopen();
         self.hardbreak_if_not_bol();
@@ -1483,14 +1512,21 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
-            ast::AssocItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
-                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+            ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
+                self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
             }
             ast::AssocItemKind::Const(def, ty, body) => {
                 self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
             }
-            ast::AssocItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+            ast::AssocItemKind::TyAlias(box ast::TyAlias { defaultness, generics, bounds, ty }) => {
+                self.print_associated_type(
+                    ident,
+                    generics,
+                    bounds,
+                    ty.as_deref(),
+                    vis,
+                    *defaultness,
+                );
             }
             ast::AssocItemKind::MacCall(m) => {
                 self.print_mac(m);
@@ -2199,8 +2235,8 @@ enum AsmArg<'a> {
 
         let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))];
         args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
-        if let Some((abi, _)) = asm.clobber_abi {
-            args.push(AsmArg::ClobberAbi(abi));
+        for (abi, _) in &asm.clobber_abis {
+            args.push(AsmArg::ClobberAbi(*abi));
         }
         if !asm.options.is_empty() {
             args.push(AsmArg::Options(asm.options));
index 15309ccd8df278ef157210533c15436bd75780ad..1bc9f8cf3ccc8660d83d41b83cfdee1ec85e4e04 100644 (file)
@@ -339,7 +339,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
     // We generally shouldn't have errors here because the query was
     // already run, but there's no point using `delay_span_bug`
     // when we're going to emit an error here anyway.
-    let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new);
+    let _errors = fulfill_cx.select_all_or_error(infcx);
 
     let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
         debug!("{:#?}", region_constraints);
index 439c728798d3a42b1b8c1717fd61a4a873103820..46a3c0fa1015248cfcc806148757693432b26c00 100644 (file)
@@ -408,7 +408,7 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
                     let param = generics.type_param(&param_ty, tcx);
                     if let Some(generics) = tcx
                         .hir()
-                        .get_generics(tcx.closure_base_def_id(self.mir_def_id().to_def_id()))
+                        .get_generics(tcx.typeck_root_def_id(self.mir_def_id().to_def_id()))
                     {
                         suggest_constraining_type_param(
                             tcx,
index d5de0801ac4431ccfcaab25872a16923501b8925..79973ab170cad8e362dd85199181b79b2e4c24ff 100644 (file)
@@ -53,10 +53,7 @@ pub(crate) enum LaterUseKind {
 
 impl BorrowExplanation {
     pub(crate) fn is_explained(&self) -> bool {
-        match self {
-            BorrowExplanation::Unexplained => false,
-            _ => true,
-        }
+        !matches!(self, BorrowExplanation::Unexplained)
     }
     pub(crate) fn add_explanation_to_diagnostic<'tcx>(
         &self,
index e5924f9d08478ff484bcf5feef030bb7a48419cc..6ffab16577908fcbc747a0a4ff2d5b72620628fb 100644 (file)
@@ -376,7 +376,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
     errors_buffer: &mut Vec<Diagnostic>,
 ) {
     let tcx = infcx.tcx;
-    let base_def_id = tcx.closure_base_def_id(body.source.def_id());
+    let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
     if !tcx.has_attr(base_def_id, sym::rustc_regions) {
         return;
     }
index 22bb3a29425ee1b49d5b44a3bc228030af3d0ac7..b39a28f79aaddc3f2eda6882bf5bd7b934fb2f9b 100644 (file)
@@ -569,7 +569,7 @@ pub(super) fn solve(
         // to store those. Otherwise, we'll pass in `None` to the
         // functions below, which will trigger them to report errors
         // eagerly.
-        let mut outlives_requirements = infcx.tcx.is_closure(mir_def_id).then(Vec::new);
+        let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new);
 
         self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer);
 
@@ -2110,14 +2110,14 @@ fn check_member_constraints(
                     _ => constraint_sup_scc != target_scc,
                 }
             } else {
-                match categorized_path[*i].category {
+                !matches!(
+                    categorized_path[*i].category,
                     ConstraintCategory::OpaqueType
-                    | ConstraintCategory::Boring
-                    | ConstraintCategory::BoringNoLocation
-                    | ConstraintCategory::Internal
-                    | ConstraintCategory::Predicate(_) => false,
-                    _ => true,
-                }
+                        | ConstraintCategory::Boring
+                        | ConstraintCategory::BoringNoLocation
+                        | ConstraintCategory::Internal
+                        | ConstraintCategory::Predicate(_)
+                )
             }
         };
 
@@ -2229,7 +2229,7 @@ fn apply_requirements(
             tcx,
             closure_substs,
             self.num_external_vids,
-            tcx.closure_base_def_id(closure_def_id),
+            tcx.typeck_root_def_id(closure_def_id),
         );
         debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
 
index 7e6a481ca69a1b76f62008c1282b3ea676662ac0..ddd077c22faf86662dfb93c482f2374dc249cd07 100644 (file)
@@ -10,6 +10,7 @@
 use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
@@ -655,7 +656,7 @@ fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Locatio
             // If the region is live at at least one location in the promoted MIR,
             // then add a liveness constraint to the main MIR for this region
             // at the location provided as an argument to this method
-            if let Some(_) = liveness_constraints.get_elements(region).next() {
+            if liveness_constraints.get_elements(region).next().is_some() {
                 self.cx
                     .borrowck_context
                     .constraints
@@ -1343,13 +1344,9 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                 // though.
                 let category = match place.as_local() {
                     Some(RETURN_PLACE) => {
-                        if let BorrowCheckContext {
-                            universal_regions:
-                                UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. },
-                            ..
-                        } = self.borrowck_context
-                        {
-                            if tcx.is_static(*def_id) {
+                        let defining_ty = &self.borrowck_context.universal_regions.defining_ty;
+                        if defining_ty.is_const() {
+                            if tcx.is_static(defining_ty.def_id()) {
                                 ConstraintCategory::UseAsStatic
                             } else {
                                 ConstraintCategory::UseAsConst
@@ -1527,6 +1524,8 @@ fn check_terminator(
                 }
             }
             TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
+                self.check_operand(discr, term_location);
+
                 let discr_ty = discr.ty(body, tcx);
                 if let Err(terr) = self.sub_types(
                     discr_ty,
@@ -1549,6 +1548,11 @@ fn check_terminator(
                 // FIXME: check the values
             }
             TerminatorKind::Call { ref func, ref args, ref destination, from_hir_call, .. } => {
+                self.check_operand(func, term_location);
+                for arg in args {
+                    self.check_operand(arg, term_location);
+                }
+
                 let func_ty = func.ty(body, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let sig = match func_ty.kind() {
@@ -1593,6 +1597,8 @@ fn check_terminator(
                 self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
             }
             TerminatorKind::Assert { ref cond, ref msg, .. } => {
+                self.check_operand(cond, term_location);
+
                 let cond_ty = cond.ty(body, tcx);
                 if cond_ty != tcx.types.bool {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
@@ -1608,6 +1614,8 @@ fn check_terminator(
                 }
             }
             TerminatorKind::Yield { ref value, .. } => {
+                self.check_operand(value, term_location);
+
                 let value_ty = value.ty(body, tcx);
                 match body.yield_ty() {
                     None => span_mirbug!(self, term, "yield in non-generator"),
@@ -1650,7 +1658,12 @@ fn check_call_dest(
                     Some(RETURN_PLACE) => {
                         if let BorrowCheckContext {
                             universal_regions:
-                                UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. },
+                                UniversalRegions {
+                                    defining_ty:
+                                        DefiningTy::Const(def_id, _)
+                                        | DefiningTy::InlineConst(def_id, _),
+                                    ..
+                                },
                             ..
                         } = self.borrowck_context
                         {
@@ -1931,15 +1944,51 @@ fn aggregate_field_ty(
         }
     }
 
+    fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.literal {
+                ConstantKind::Ty(ct) => match ct.val {
+                    ty::ConstKind::Unevaluated(uv) => Some(uv),
+                    _ => None,
+                },
+                _ => None,
+            };
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let tcx = self.tcx();
+                    let def_id = uv.def.def_id_for_type_of();
+                    if tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let predicates = self.prove_closure_bounds(
+                            tcx,
+                            def_id.expect_local(),
+                            uv.substs(tcx),
+                            location,
+                        );
+                        self.normalize_and_prove_instantiated_predicates(
+                            def_id,
+                            predicates,
+                            location.to_locations(),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
     fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
         let tcx = self.tcx();
 
         match rvalue {
             Rvalue::Aggregate(ak, ops) => {
+                for op in ops {
+                    self.check_operand(op, location);
+                }
                 self.check_aggregate_rvalue(&body, rvalue, ak, ops, location)
             }
 
             Rvalue::Repeat(operand, len) => {
+                self.check_operand(operand, location);
+
                 // If the length cannot be evaluated we must assume that the length can be larger
                 // than 1.
                 // If the length is larger than 1, the repeat expression will need to copy the
@@ -1990,7 +2039,22 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
             }
 
-            Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, ty) => {
+            Rvalue::NullaryOp(_, ty) => {
+                let trait_ref = ty::TraitRef {
+                    def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
+                    substs: tcx.mk_substs_trait(ty, &[]),
+                };
+
+                self.prove_trait_ref(
+                    trait_ref,
+                    location.to_locations(),
+                    ConstraintCategory::SizedBound,
+                );
+            }
+
+            Rvalue::ShallowInitBox(operand, ty) => {
+                self.check_operand(operand, location);
+
                 let trait_ref = ty::TraitRef {
                     def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                     substs: tcx.mk_substs_trait(ty, &[]),
@@ -2004,6 +2068,8 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
             }
 
             Rvalue::Cast(cast_kind, op, ty) => {
+                self.check_operand(op, location);
+
                 match cast_kind {
                     CastKind::Pointer(PointerCast::ReifyFnPointer) => {
                         let fn_sig = op.ty(body, tcx).fn_sig(tcx);
@@ -2250,6 +2316,9 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
                 box (left, right),
             ) => {
+                self.check_operand(left, location);
+                self.check_operand(right, location);
+
                 let ty_left = left.ty(body, tcx);
                 match ty_left.kind() {
                     // Types with regions are comparable if they have a common super-type.
@@ -2300,13 +2369,19 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
             }
 
+            Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => {
+                self.check_operand(operand, location);
+            }
+
+            Rvalue::BinaryOp(_, box (left, right))
+            | Rvalue::CheckedBinaryOp(_, box (left, right)) => {
+                self.check_operand(left, location);
+                self.check_operand(right, location);
+            }
+
             Rvalue::AddressOf(..)
             | Rvalue::ThreadLocalRef(..)
-            | Rvalue::Use(..)
             | Rvalue::Len(..)
-            | Rvalue::BinaryOp(..)
-            | Rvalue::CheckedBinaryOp(..)
-            | Rvalue::UnaryOp(..)
             | Rvalue::Discriminant(..) => {}
         }
     }
index bebd19370299d00cdf360796c578638612f80312..b986df403f9f3f2c97789bad02c2b9720708bd71 100644 (file)
@@ -23,7 +23,7 @@
 use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
 use std::iter;
 
 use crate::nll::ToRegionVid;
@@ -108,6 +108,10 @@ pub enum DefiningTy<'tcx> {
     /// is that it has no inputs and a single return value, which is
     /// the value of the constant.
     Const(DefId, SubstsRef<'tcx>),
+
+    /// The MIR represents an inline const. The signature has no inputs and a
+    /// single return value found via `InlineConstSubsts::ty`.
+    InlineConst(DefId, SubstsRef<'tcx>),
 }
 
 impl<'tcx> DefiningTy<'tcx> {
@@ -121,7 +125,7 @@ pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
             DefiningTy::Generator(_, substs, _) => {
                 Either::Right(Either::Left(substs.as_generator().upvar_tys()))
             }
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) => {
+            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
                 Either::Right(Either::Right(iter::empty()))
             }
         }
@@ -133,22 +137,16 @@ pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
     pub fn implicit_inputs(self) -> usize {
         match self {
             DefiningTy::Closure(..) | DefiningTy::Generator(..) => 1,
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) => 0,
+            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
         }
     }
 
     pub fn is_fn_def(&self) -> bool {
-        match *self {
-            DefiningTy::FnDef(..) => true,
-            _ => false,
-        }
+        matches!(*self, DefiningTy::FnDef(..))
     }
 
     pub fn is_const(&self) -> bool {
-        match *self {
-            DefiningTy::Const(..) => true,
-            _ => false,
-        }
+        matches!(*self, DefiningTy::Const(..) | DefiningTy::InlineConst(..))
     }
 
     pub fn def_id(&self) -> DefId {
@@ -156,7 +154,8 @@ pub fn def_id(&self) -> DefId {
             DefiningTy::Closure(def_id, ..)
             | DefiningTy::Generator(def_id, ..)
             | DefiningTy::FnDef(def_id, ..)
-            | DefiningTy::Const(def_id, ..) => def_id,
+            | DefiningTy::Const(def_id, ..)
+            | DefiningTy::InlineConst(def_id, ..) => def_id,
         }
     }
 }
@@ -248,7 +247,7 @@ pub fn closure_mapping(
         tcx: TyCtxt<'tcx>,
         closure_substs: SubstsRef<'tcx>,
         expected_num_vars: usize,
-        closure_base_def_id: DefId,
+        typeck_root_def_id: DefId,
     ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
         let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
         region_mapping.push(tcx.lifetimes.re_static);
@@ -256,7 +255,7 @@ pub fn closure_mapping(
             region_mapping.push(fr);
         });
 
-        for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+        for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
             region_mapping.push(r);
         });
 
@@ -350,8 +349,8 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                 // tests, and the resulting print-outs include def-ids
                 // and other things that are not stable across tests!
                 // So we just include the region-vid. Annoying.
-                let closure_base_def_id = tcx.closure_base_def_id(def_id);
-                for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+                for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
                     err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
                 });
             }
@@ -365,8 +364,8 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                 // FIXME: As above, we'd like to print out the region
                 // `r` but doing so is not stable across architectures
                 // and so forth.
-                let closure_base_def_id = tcx.closure_base_def_id(def_id);
-                for_each_late_bound_region_defined_on(tcx, closure_base_def_id, |r| {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+                for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
                     err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
                 });
             }
@@ -382,6 +381,12 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
                     tcx.def_path_str_with_substs(def_id, substs),
                 ));
             }
+            DefiningTy::InlineConst(def_id, substs) => {
+                err.note(&format!(
+                    "defining inline constant type: {}",
+                    tcx.def_path_str_with_substs(def_id, substs),
+                ));
+            }
         }
     }
 }
@@ -417,7 +422,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         let mut indices = self.compute_indices(fr_static, defining_ty);
         debug!("build: indices={:?}", indices);
 
-        let closure_base_def_id = self.infcx.tcx.closure_base_def_id(self.mir_def.did.to_def_id());
+        let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
 
         // If this is a closure or generator, then the late-bound regions from the enclosing
         // function are actually external regions to us. For example, here, 'a is not local
@@ -425,7 +430,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         // fn foo<'a>() {
         //     let c = || { let x: &'a u32 = ...; }
         // }
-        if self.mir_def.did.to_def_id() != closure_base_def_id {
+        if self.mir_def.did.to_def_id() != typeck_root_def_id {
             self.infcx
                 .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices)
         }
@@ -443,7 +448,7 @@ fn build(self) -> UniversalRegions<'tcx> {
         );
         // Converse of above, if this is a function then the late-bound regions declared on its
         // signature are local to the fn.
-        if self.mir_def.did.to_def_id() == closure_base_def_id {
+        if self.mir_def.did.to_def_id() == typeck_root_def_id {
             self.infcx
                 .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
         }
@@ -508,12 +513,12 @@ fn build(self) -> UniversalRegions<'tcx> {
     /// see `DefiningTy` for details.
     fn defining_ty(&self) -> DefiningTy<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
+        let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
 
         match tcx.hir().body_owner_kind(self.mir_hir_id) {
             BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
-                let defining_ty = if self.mir_def.did.to_def_id() == closure_base_def_id {
-                    tcx.type_of(closure_base_def_id)
+                let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
+                    tcx.type_of(typeck_root_def_id)
                 } else {
                     let tables = tcx.typeck(self.mir_def.did);
                     tables.node_type(self.mir_hir_id)
@@ -540,11 +545,21 @@ fn defining_ty(&self) -> DefiningTy<'tcx> {
             }
 
             BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
-                assert_eq!(self.mir_def.did.to_def_id(), closure_base_def_id);
-                let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
-                let substs =
-                    self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
-                DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
+                let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
+                if self.mir_def.did.to_def_id() == typeck_root_def_id {
+                    let substs =
+                        self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
+                    DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
+                } else {
+                    let ty = tcx.typeck(self.mir_def.did).node_type(self.mir_hir_id);
+                    let substs = InlineConstSubsts::new(
+                        tcx,
+                        InlineConstSubstsParts { parent_substs: identity_substs, ty },
+                    )
+                    .substs;
+                    let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs);
+                    DefiningTy::InlineConst(self.mir_def.did.to_def_id(), substs)
+                }
             }
         }
     }
@@ -559,17 +574,19 @@ fn compute_indices(
         defining_ty: DefiningTy<'tcx>,
     ) -> UniversalRegionIndices<'tcx> {
         let tcx = self.infcx.tcx;
-        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def.did.to_def_id());
-        let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
+        let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
+        let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
         let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, ref substs) | DefiningTy::Generator(_, ref substs, _) => {
+            DefiningTy::Closure(_, ref substs)
+            | DefiningTy::Generator(_, ref substs, _)
+            | DefiningTy::InlineConst(_, ref substs) => {
                 // In the case of closures, we rely on the fact that
                 // the first N elements in the ClosureSubsts are
-                // inherited from the `closure_base_def_id`.
+                // inherited from the `typeck_root_def_id`.
                 // Therefore, when we zip together (below) with
                 // `identity_substs`, we will get only those regions
                 // that correspond to early-bound regions declared on
-                // the `closure_base_def_id`.
+                // the `typeck_root_def_id`.
                 assert!(substs.len() >= identity_substs.len());
                 assert_eq!(substs.regions().count(), identity_substs.regions().count());
                 substs
@@ -654,6 +671,12 @@ fn compute_inputs_and_output(
                 let ty = indices.fold_to_region_vids(tcx, ty);
                 ty::Binder::dummy(tcx.intern_type_list(&[ty]))
             }
+
+            DefiningTy::InlineConst(def_id, substs) => {
+                assert_eq!(self.mir_def.did.to_def_id(), def_id);
+                let ty = substs.as_inline_const().ty();
+                ty::Binder::dummy(tcx.intern_type_list(&[ty]))
+            }
         }
     }
 }
@@ -742,8 +765,8 @@ fn replace_late_bound_regions_with_nll_infer_vars(
         indices: &mut UniversalRegionIndices<'tcx>,
     ) {
         debug!("replace_late_bound_regions_with_nll_infer_vars(mir_def_id={:?})", mir_def_id);
-        let closure_base_def_id = self.tcx.closure_base_def_id(mir_def_id.to_def_id());
-        for_each_late_bound_region_defined_on(self.tcx, closure_base_def_id, |r| {
+        let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id());
+        for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| {
             debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = self.next_nll_region_var(FR);
index 198287f608e3973d318d9d4e6e869be0dbd48c26..41662f46f115296e821e0a932a1601ceee4bf42d 100644 (file)
@@ -19,7 +19,7 @@ struct AsmArgs {
     operands: Vec<(ast::InlineAsmOperand, Span)>,
     named_args: FxHashMap<Symbol, usize>,
     reg_args: FxHashSet<usize>,
-    clobber_abi: Option<(Symbol, Span)>,
+    clobber_abis: Vec<(Symbol, Span)>,
     options: ast::InlineAsmOptions,
     options_spans: Vec<Span>,
 }
@@ -64,7 +64,7 @@ fn parse_args<'a>(
         operands: vec![],
         named_args: FxHashMap::default(),
         reg_args: FxHashSet::default(),
-        clobber_abi: None,
+        clobber_abis: Vec::new(),
         options: ast::InlineAsmOptions::empty(),
         options_spans: vec![],
     };
@@ -210,9 +210,9 @@ fn parse_args<'a>(
                 .span_labels(args.options_spans.clone(), "previous options")
                 .span_label(span, "argument")
                 .emit();
-        } else if let Some((_, abi_span)) = args.clobber_abi {
+        } else if let Some((_, abi_span)) = args.clobber_abis.last() {
             ecx.struct_span_err(span, "arguments are not allowed after clobber_abi")
-                .span_label(abi_span, "clobber_abi")
+                .span_label(*abi_span, "clobber_abi")
                 .span_label(span, "argument")
                 .emit();
         }
@@ -322,10 +322,13 @@ fn parse_args<'a>(
         // Bail out now since this is likely to confuse MIR
         return Err(err);
     }
-    if let Some((_, abi_span)) = args.clobber_abi {
+
+    if args.clobber_abis.len() > 0 {
         if is_global_asm {
-            let err =
-                ecx.struct_span_err(abi_span, "`clobber_abi` cannot be used with `global_asm!`");
+            let err = ecx.struct_span_err(
+                args.clobber_abis.iter().map(|(_, span)| *span).collect::<Vec<Span>>(),
+                "`clobber_abi` cannot be used with `global_asm!`",
+            );
 
             // Bail out now since this is likely to confuse later stages
             return Err(err);
@@ -335,7 +338,10 @@ fn parse_args<'a>(
                 regclass_outputs.clone(),
                 "asm with `clobber_abi` must specify explicit registers for outputs",
             )
-            .span_label(abi_span, "clobber_abi")
+            .span_labels(
+                args.clobber_abis.iter().map(|(_, span)| *span).collect::<Vec<Span>>(),
+                "clobber_abi",
+            )
             .span_labels(regclass_outputs, "generic outputs")
             .emit();
         }
@@ -439,37 +445,61 @@ fn parse_clobber_abi<'a>(
 
     p.expect(&token::OpenDelim(token::DelimToken::Paren))?;
 
-    let clobber_abi = match p.parse_str_lit() {
-        Ok(str_lit) => str_lit.symbol_unescaped,
-        Err(opt_lit) => {
-            let span = opt_lit.map_or(p.token.span, |lit| lit.span);
-            let mut err = p.sess.span_diagnostic.struct_span_err(span, "expected string literal");
-            err.span_label(span, "not a string literal");
-            return Err(err);
-        }
-    };
+    if p.eat(&token::CloseDelim(token::DelimToken::Paren)) {
+        let err = p.sess.span_diagnostic.struct_span_err(
+            p.token.span,
+            "at least one abi must be provided as an argument to `clobber_abi`",
+        );
+        return Err(err);
+    }
 
-    p.expect(&token::CloseDelim(token::DelimToken::Paren))?;
+    let mut new_abis = Vec::new();
+    loop {
+        match p.parse_str_lit() {
+            Ok(str_lit) => {
+                new_abis.push((str_lit.symbol_unescaped, str_lit.span));
+            }
+            Err(opt_lit) => {
+                // If the non-string literal is a closing paren then it's the end of the list and is fine
+                if p.eat(&token::CloseDelim(token::DelimToken::Paren)) {
+                    break;
+                }
+                let span = opt_lit.map_or(p.token.span, |lit| lit.span);
+                let mut err =
+                    p.sess.span_diagnostic.struct_span_err(span, "expected string literal");
+                err.span_label(span, "not a string literal");
+                return Err(err);
+            }
+        };
 
-    let new_span = span_start.to(p.prev_token.span);
+        // Allow trailing commas
+        if p.eat(&token::CloseDelim(token::DelimToken::Paren)) {
+            break;
+        }
+        p.expect(&token::Comma)?;
+    }
 
-    if let Some((_, prev_span)) = args.clobber_abi {
-        let mut err = p
-            .sess
-            .span_diagnostic
-            .struct_span_err(new_span, "clobber_abi specified multiple times");
-        err.span_label(prev_span, "clobber_abi previously specified here");
-        return Err(err);
-    } else if !args.options_spans.is_empty() {
+    let full_span = span_start.to(p.prev_token.span);
+
+    if !args.options_spans.is_empty() {
         let mut err = p
             .sess
             .span_diagnostic
-            .struct_span_err(new_span, "clobber_abi is not allowed after options");
+            .struct_span_err(full_span, "clobber_abi is not allowed after options");
         err.span_labels(args.options_spans.clone(), "options");
         return Err(err);
     }
 
-    args.clobber_abi = Some((clobber_abi, new_span));
+    match &new_abis[..] {
+        // should have errored above during parsing
+        [] => unreachable!(),
+        [(abi, _span)] => args.clobber_abis.push((*abi, full_span)),
+        [abis @ ..] => {
+            for (abi, span) in abis {
+                args.clobber_abis.push((*abi, *span));
+            }
+        }
+    }
 
     Ok(())
 }
@@ -547,7 +577,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                 if let Some(snippet) = &template_snippet {
                     if let Some(pos) = snippet.find(needle) {
                         let end = pos
-                            + &snippet[pos..]
+                            + snippet[pos..]
                                 .find(|c| matches!(c, '\n' | ';' | '\\' | '"'))
                                 .unwrap_or(snippet[pos..].len() - 1);
                         let inner = InnerSpan::new(pos, end);
@@ -770,7 +800,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
         template,
         template_strs: template_strs.into_boxed_slice(),
         operands: args.operands,
-        clobber_abi: args.clobber_abi,
+        clobber_abis: args.clobber_abis,
         options: args.options,
         line_spans,
     })
@@ -815,7 +845,7 @@ pub fn expand_global_asm<'cx>(
                     ident: Ident::empty(),
                     attrs: Vec::new(),
                     id: ast::DUMMY_NODE_ID,
-                    kind: ast::ItemKind::GlobalAsm(inline_asm),
+                    kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
                     vis: ast::Visibility {
                         span: sp.shrink_to_lo(),
                         kind: ast::VisibilityKind::Inherited,
index a225b328ab6a4fc205c260e5bce01e440866384c..994a74a5a9b9f939190f50b3bcfa5184b3f9f4bb 100644 (file)
@@ -557,12 +557,12 @@ fn create_derived_impl(
                     tokens: None,
                 },
                 attrs: Vec::new(),
-                kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAliasKind(
-                    ast::Defaultness::Final,
-                    Generics::default(),
-                    Vec::new(),
-                    Some(type_def.to_ty(cx, self.span, type_ident, generics)),
-                ))),
+                kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
+                    defaultness: ast::Defaultness::Final,
+                    generics: Generics::default(),
+                    bounds: Vec::new(),
+                    ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
+                })),
                 tokens: None,
             })
         });
@@ -726,7 +726,7 @@ fn create_derived_impl(
             self.span,
             Ident::empty(),
             a,
-            ast::ItemKind::Impl(Box::new(ast::ImplKind {
+            ast::ItemKind::Impl(Box::new(ast::Impl {
                 unsafety,
                 polarity: ast::ImplPolarity::Positive,
                 defaultness: ast::Defaultness::Final,
@@ -955,7 +955,7 @@ fn create_method(
             decl: fn_decl,
             span: trait_.span,
         };
-        let def = ast::Defaultness::Final;
+        let defaultness = ast::Defaultness::Final;
 
         // Create the method.
         P(ast::AssocItem {
@@ -968,12 +968,12 @@ fn create_method(
                 tokens: None,
             },
             ident: method_ident,
-            kind: ast::AssocItemKind::Fn(Box::new(ast::FnKind(
-                def,
+            kind: ast::AssocItemKind::Fn(Box::new(ast::Fn {
+                defaultness,
                 sig,
-                fn_generics,
-                Some(body_block),
-            ))),
+                generics: fn_generics,
+                body: Some(body_block),
+            })),
             tokens: None,
         })
     }
index fa389a51115782696ef49c9d7a7c860aaab1e624..367a5aa732370a0dff03491b22f151322989206e 100644 (file)
@@ -2,7 +2,7 @@
 
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
-use rustc_ast::{ImplKind, ItemKind, MetaItem};
+use rustc_ast::{Impl, ItemKind, MetaItem};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
@@ -180,7 +180,7 @@ fn inject_impl_of_structural_trait(
         span,
         Ident::empty(),
         attrs,
-        ItemKind::Impl(Box::new(ImplKind {
+        ItemKind::Impl(Box::new(Impl {
             unsafety: ast::Unsafe::No,
             polarity: ast::ImplPolarity::Positive,
             defaultness: ast::Defaultness::Final,
index f0056cb79766a49f4db2f34a68a81b93c5176063..52b00a2bc74746d9d0fddbe3ff592ebd4f690774 100644 (file)
@@ -760,16 +760,11 @@ fn build_piece(
     /// Actually builds the expression which the format_args! block will be
     /// expanded to.
     fn into_expr(self) -> P<ast::Expr> {
-        let mut locals =
-            Vec::with_capacity((0..self.args.len()).map(|i| self.arg_unique_types[i].len()).sum());
-        let mut counts = Vec::with_capacity(self.count_args.len());
-        let mut pats = Vec::with_capacity(self.args.len());
+        let mut args = Vec::with_capacity(
+            self.arg_unique_types.iter().map(|v| v.len()).sum::<usize>() + self.count_args.len(),
+        );
         let mut heads = Vec::with_capacity(self.args.len());
 
-        let names_pos: Vec<_> = (0..self.args.len())
-            .map(|i| Ident::from_str_and_span(&format!("arg{}", i), self.macsp))
-            .collect();
-
         // First, build up the static array which will become our precompiled
         // format "string"
         let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces);
@@ -787,11 +782,8 @@ fn into_expr(self) -> P<ast::Expr> {
         // of each variable because we don't want to move out of the arguments
         // passed to this function.
         for (i, e) in self.args.into_iter().enumerate() {
-            let name = names_pos[i];
-            let span = self.ecx.with_def_site_ctxt(e.span);
-            pats.push(self.ecx.pat_ident(span, name));
             for arg_ty in self.arg_unique_types[i].iter() {
-                locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name));
+                args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i));
             }
             heads.push(self.ecx.expr_addr_of(e.span, e));
         }
@@ -800,15 +792,11 @@ fn into_expr(self) -> P<ast::Expr> {
                 Exact(i) => i,
                 _ => panic!("should never happen"),
             };
-            let name = names_pos[index];
             let span = spans_pos[index];
-            counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name));
+            args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index));
         }
 
-        // Now create a vector containing all the arguments
-        let args = locals.into_iter().chain(counts.into_iter());
-
-        let args_array = self.ecx.expr_vec(self.macsp, args.collect());
+        let args_array = self.ecx.expr_vec(self.macsp, args);
 
         // Constructs an AST equivalent to:
         //
@@ -838,7 +826,7 @@ fn into_expr(self) -> P<ast::Expr> {
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
         let args_match = {
-            let pat = self.ecx.pat_tuple(self.macsp, pats);
+            let pat = self.ecx.pat_ident(self.macsp, Ident::new(sym::_args, self.macsp));
             let arm = self.ecx.arm(self.macsp, pat, args_array);
             let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
             self.ecx.expr_match(self.macsp, head, vec![arm])
@@ -877,10 +865,11 @@ fn format_arg(
         macsp: Span,
         mut sp: Span,
         ty: &ArgumentType,
-        arg: Ident,
+        arg_index: usize,
     ) -> P<ast::Expr> {
         sp = ecx.with_def_site_ctxt(sp);
-        let arg = ecx.expr_ident(sp, arg);
+        let arg = ecx.expr_ident(sp, Ident::new(sym::_args, sp));
+        let arg = ecx.expr(sp, ast::ExprKind::Field(arg, Ident::new(sym::integer(arg_index), sp)));
         let trait_ = match *ty {
             Placeholder(trait_) if trait_ == "<invalid>" => return DummyResult::raw_expr(sp, true),
             Placeholder(trait_) => trait_,
index 3f71ee6f489a08fbbdd1d413f92905f9fe769417..a433876147f8d903edbc8568485649f5eef0cf92 100644 (file)
@@ -5,7 +5,7 @@
 };
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
-use rustc_ast::{FnKind, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
+use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
@@ -84,13 +84,13 @@ fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
         let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
         let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
         let sig = FnSig { decl, header, span: self.span };
-        let block = Some(self.cx.block_expr(output_expr));
-        let kind = ItemKind::Fn(Box::new(FnKind(
-            ast::Defaultness::Final,
+        let body = Some(self.cx.block_expr(output_expr));
+        let kind = ItemKind::Fn(Box::new(Fn {
+            defaultness: ast::Defaultness::Final,
             sig,
-            Generics::default(),
-            block,
-        )));
+            generics: Generics::default(),
+            body,
+        }));
         let item = self.cx.item(
             self.span,
             Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span),
index bbca07085ea3615043d6b0db868459dc68c39de9..d2629926b51da705f3ae4e1dfbb28b9c1f54911d 100644 (file)
@@ -429,7 +429,7 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
 fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
     let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
     let sd = &cx.sess.parse_sess.span_diagnostic;
-    if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, ref generics, _)) = i.kind {
+    if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
         if let ast::Unsafe::Yes(span) = sig.header.unsafety {
             sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
                 .span_label(span, "`unsafe` because of this")
@@ -478,7 +478,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
 }
 
 fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
-    let has_sig = if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) = i.kind {
+    let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
         // N.B., inadequate check, but we're running
         // well before resolve, can't get too deep.
         sig.decl.inputs.len() == 1
index d791677cb8ee1adbd64cd24f9df8aa3fe5aa1c2c..64ccd4331e58a7c3492840e3bba07e8d88452e4b 100644 (file)
@@ -313,13 +313,13 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
     let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
     let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
-    let def = ast::Defaultness::Final;
-    let main = ast::ItemKind::Fn(Box::new(ast::FnKind(
-        def,
+    let defaultness = ast::Defaultness::Final;
+    let main = ast::ItemKind::Fn(Box::new(ast::Fn {
+        defaultness,
         sig,
-        ast::Generics::default(),
-        Some(main_body),
-    )));
+        generics: ast::Generics::default(),
+        body: Some(main_body),
+    }));
 
     // Honor the reexport_test_harness_main attribute
     let main_id = match cx.reexport_test_harness_main {
index 82c3c2006eb148f8cb5bb72ac913cc47c8c77686..3d05fc15b38f4121c22f737cccc040d78f734db2 100644 (file)
@@ -17,6 +17,7 @@
 };
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
+use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_errors::{FatalError, Handler, Level};
 use rustc_fs_util::{link_or_copy, path_to_c_string};
@@ -53,6 +54,7 @@ pub fn write_output_file(
     output: &Path,
     dwo_output: Option<&Path>,
     file_type: llvm::FileType,
+    self_profiler_ref: &SelfProfilerRef,
 ) -> Result<(), FatalError> {
     unsafe {
         let output_c = path_to_c_string(output);
@@ -76,6 +78,19 @@ pub fn write_output_file(
                 file_type,
             )
         };
+
+        // Record artifact sizes for self-profiling
+        if result == llvm::LLVMRustResult::Success {
+            let artifact_kind = match file_type {
+                llvm::FileType::ObjectFile => "object_file",
+                llvm::FileType::AssemblyFile => "assembly_file",
+            };
+            record_artifact_size(self_profiler_ref, artifact_kind, output);
+            if let Some(dwo_file) = dwo_output {
+                record_artifact_size(self_profiler_ref, "dwo_file", dwo_file);
+            }
+        }
+
         result.into_result().map_err(|()| {
             let msg = format!("could not write output to {}", output.display());
             llvm_err(handler, &msg)
@@ -286,7 +301,7 @@ fn report_inline_asm(
         cookie = 0;
     }
     let level = match level {
-        llvm::DiagnosticLevel::Error => Level::Error,
+        llvm::DiagnosticLevel::Error => Level::Error { lint: false },
         llvm::DiagnosticLevel::Warning => Level::Warning,
         llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
     };
@@ -752,6 +767,14 @@ unsafe fn with_codegen<'ll, F, R>(
             let thin = ThinBuffer::new(llmod);
             let data = thin.data();
 
+            if let Some(bitcode_filename) = bc_out.file_name() {
+                cgcx.prof.artifact_size(
+                    "llvm_bitcode",
+                    bitcode_filename.to_string_lossy(),
+                    data.len() as u64,
+                );
+            }
+
             if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
                 let _timer = cgcx.prof.generic_activity_with_arg(
                     "LLVM_module_codegen_emit_bitcode",
@@ -812,6 +835,11 @@ extern "C" fn demangle_callback(
             }
 
             let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
+
+            if result == llvm::LLVMRustResult::Success {
+                record_artifact_size(&cgcx.prof, "llvm_ir", &out);
+            }
+
             result.into_result().map_err(|()| {
                 let msg = format!("failed to write LLVM IR to {}", out.display());
                 llvm_err(diag_handler, &msg)
@@ -842,6 +870,7 @@ extern "C" fn demangle_callback(
                     &path,
                     None,
                     llvm::FileType::AssemblyFile,
+                    &cgcx.prof,
                 )
             })?;
         }
@@ -875,6 +904,7 @@ extern "C" fn demangle_callback(
                         &obj_out,
                         dwo_out,
                         llvm::FileType::ObjectFile,
+                        &cgcx.prof,
                     )
                 })?;
             }
@@ -1131,3 +1161,19 @@ fn ignored(symbol_name: &[u8]) -> bool {
         symbol_name.starts_with(b"__llvm_profile_")
     }
 }
+
+fn record_artifact_size(
+    self_profiler_ref: &SelfProfilerRef,
+    artifact_kind: &'static str,
+    path: &Path,
+) {
+    // Don't stat the file if we are not going to record its size.
+    if !self_profiler_ref.enabled() {
+        return;
+    }
+
+    if let Some(artifact_name) = path.file_name() {
+        let file_size = std::fs::metadata(path).map(|m| m.len()).unwrap_or(0);
+        self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size);
+    }
+}
index 1f1bd73c7d035d51ae736dae5bfde264980b1d0a..2a6bf7d9b1a4ddac535843a25a4c2e052bd79ac1 100644 (file)
@@ -322,7 +322,7 @@ fn dbg_scope_fn(
         type_names::push_item_name(self.tcx(), def_id, false, &mut name);
 
         // Find the enclosing function, in case this is a closure.
-        let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
+        let enclosing_fn_def_id = self.tcx().typeck_root_def_id(def_id);
 
         // Get_template_parameters() will append a `<...>` clause to the function
         // name if necessary.
index e63fb22829a3f5b9789f3ab4f95a54ec1e97a404..924bb803b368fb850a4c7b1c208cc5f473f6b225 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, symbol::kw, Span, Symbol};
-use rustc_target::abi::{self, HasDataLayout, Primitive};
+use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
 use rustc_target::spec::{HasTargetSpec, PanicStrategy};
 
 use std::cmp::Ordering;
@@ -857,28 +857,39 @@ macro_rules! require_simd {
     let arg_tys = sig.inputs();
 
     if name == sym::simd_select_bitmask {
-        let in_ty = arg_tys[0];
-        let m_len = match in_ty.kind() {
-            // Note that this `.unwrap()` crashes for isize/usize, that's sort
-            // of intentional as there's not currently a use case for that.
-            ty::Int(i) => i.bit_width().unwrap(),
-            ty::Uint(i) => i.bit_width().unwrap(),
-            _ => return_error!("`{}` is not an integral type", in_ty),
-        };
         require_simd!(arg_tys[1], "argument");
-        let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
-        require!(
-            // Allow masks for vectors with fewer than 8 elements to be
-            // represented with a u8 or i8.
-            m_len == v_len || (m_len == 8 && v_len < 8),
-            "mismatched lengths: mask length `{}` != other vector length `{}`",
-            m_len,
-            v_len
-        );
+        let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
+
+        let expected_int_bits = (len.max(8) - 1).next_power_of_two();
+        let expected_bytes = len / 8 + ((len % 8 > 0) as u64);
+
+        let mask_ty = arg_tys[0];
+        let mask = match mask_ty.kind() {
+            ty::Int(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
+            ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
+            ty::Array(elem, len)
+                if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
+                    && len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
+                        == Some(expected_bytes) =>
+            {
+                let place = PlaceRef::alloca(bx, args[0].layout);
+                args[0].val.store(bx, place);
+                let int_ty = bx.type_ix(expected_bytes * 8);
+                let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
+                bx.load(int_ty, ptr, Align::ONE)
+            }
+            _ => return_error!(
+                "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`",
+                mask_ty,
+                expected_int_bits,
+                expected_bytes
+            ),
+        };
+
         let i1 = bx.type_i1();
-        let im = bx.type_ix(v_len);
-        let i1xn = bx.type_vector(i1, v_len);
-        let m_im = bx.trunc(args[0].immediate(), im);
+        let im = bx.type_ix(len);
+        let i1xn = bx.type_vector(i1, len);
+        let m_im = bx.trunc(mask, im);
         let m_i1s = bx.bitcast(m_im, i1xn);
         return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
     }
@@ -1056,16 +1067,16 @@ macro_rules! require_simd {
 
     if name == sym::simd_bitmask {
         // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
-        // vector mask and returns an unsigned integer containing the most
-        // significant bit (MSB) of each lane.
-
-        // If the vector has less than 8 lanes, a u8 is returned with zeroed
-        // trailing bits.
+        // vector mask and returns the most significant bit (MSB) of each lane in the form
+        // of either:
+        // * an unsigned integer
+        // * an array of `u8`
+        // If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
+        //
+        // The bit order of the result depends on the byte endianness, LSB-first for little
+        // endian and MSB-first for big endian.
         let expected_int_bits = in_len.max(8);
-        match ret_ty.kind() {
-            ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (),
-            _ => return_error!("bitmask `{}`, expected `u{}`", ret_ty, expected_int_bits),
-        }
+        let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
 
         // Integer vector <i{in_bitwidth} x in_len>:
         let (i_xn, in_elem_bitwidth) = match in_elem.kind() {
@@ -1095,8 +1106,34 @@ macro_rules! require_simd {
         let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len));
         // Bitcast <i1 x N> to iN:
         let i_ = bx.bitcast(i1xn, bx.type_ix(in_len));
-        // Zero-extend iN to the bitmask type:
-        return Ok(bx.zext(i_, bx.type_ix(expected_int_bits)));
+
+        match ret_ty.kind() {
+            ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {
+                // Zero-extend iN to the bitmask type:
+                return Ok(bx.zext(i_, bx.type_ix(expected_int_bits)));
+            }
+            ty::Array(elem, len)
+                if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
+                    && len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
+                        == Some(expected_bytes) =>
+            {
+                // Zero-extend iN to the array lengh:
+                let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
+
+                // Convert the integer to a byte array
+                let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
+                bx.store(ze, ptr, Align::ONE);
+                let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
+                let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));
+                return Ok(bx.load(array_ty, ptr, Align::ONE));
+            }
+            _ => return_error!(
+                "cannot return `{}`, expected `u{}` or `[u8; {}]`",
+                ret_ty,
+                expected_int_bits,
+                expected_bytes
+            ),
+        }
     }
 
     fn simd_simple_float_intrinsic(
index be50911f4e143a8b5cb91fc4e0c8d344c9600982..1ba0c4fa05b5b3688c3345511efb74131e3e9a7c 100644 (file)
@@ -121,6 +121,19 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
             if sess.opts.json_artifact_notifications {
                 sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link");
             }
+
+            if sess.prof.enabled() {
+                if let Some(artifact_name) = out_filename.file_name() {
+                    // Record size for self-profiling
+                    let file_size = std::fs::metadata(&out_filename).map(|m| m.len()).unwrap_or(0);
+
+                    sess.prof.artifact_size(
+                        "linked_artifact",
+                        artifact_name.to_string_lossy(),
+                        file_size,
+                    );
+                }
+            }
         }
     }
 
@@ -1095,10 +1108,10 @@ fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut d
 }
 
 fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
-    fn find_sanitizer_runtime(sess: &Session, filename: &String) -> PathBuf {
+    fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf {
         let session_tlib =
             filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple());
-        let path = session_tlib.join(&filename);
+        let path = session_tlib.join(filename);
         if path.exists() {
             return session_tlib;
         } else {
index b2edc6c0183a0b8ce13475e2d3b406c18105221a..85d51ea9a207b1cfebe505d9203ee53e55dc9a35 100644 (file)
@@ -1757,7 +1757,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
                     let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
 
                     let mut err = match level {
-                        Level::Error => sess.struct_err(&msg),
+                        Level::Error { lint: false } => sess.struct_err(&msg),
                         Level::Warning => sess.struct_warn(&msg),
                         Level::Note => sess.struct_note_without_error(&msg),
                         _ => bug!("Invalid inline asm diagnostic level"),
index accb54e464553292fcd567093f4743a4fa453122..ab119ae25f5e89d496b69388ce65ab9058b4131b 100644 (file)
@@ -124,10 +124,7 @@ fn push_debuginfo_type_name<'tcx>(
             // info for MSVC debugger. However, wrapping these types' names in a synthetic type
             // causes the .natvis engine for WinDbg to fail to display their data, so we opt these
             // types out to aid debugging in MSVC.
-            let is_slice_or_str = match *inner_type.kind() {
-                ty::Slice(_) | ty::Str => true,
-                _ => false,
-            };
+            let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str);
 
             if !cpp_like_names {
                 output.push('&');
index caeeb23feb471bf48f86dcc753c44daf94adf7b1..b4420df5df417a67196e3b4c70c7013449ea2cff 100644 (file)
@@ -20,6 +20,7 @@
     ("aes", Some(sym::arm_target_feature)),
     ("sha2", Some(sym::arm_target_feature)),
     ("i8mm", Some(sym::arm_target_feature)),
+    ("dotprod", Some(sym::arm_target_feature)),
     ("v5te", Some(sym::arm_target_feature)),
     ("v6", Some(sym::arm_target_feature)),
     ("v6k", Some(sym::arm_target_feature)),
index 5da1681662577648009f96b1da5b0aabfe02229d..87298023980ed8c2ff2ccde238122e1a7556fb53 100644 (file)
@@ -25,10 +25,7 @@ pub enum ConstEvalErrKind {
 
 impl MachineStopType for ConstEvalErrKind {
     fn is_hard_err(&self) -> bool {
-        match self {
-            Self::Panic { .. } => true,
-            _ => false,
-        }
+        matches!(self, Self::Panic { .. })
     }
 }
 
index 57af0ff07143373cacfd7f11d2423e7e0bc8cd7c..6d3a89c0a8a5ba3927510556463c1b55d4397baa 100644 (file)
@@ -42,6 +42,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
                     | DefKind::Static
                     | DefKind::ConstParam
                     | DefKind::AnonConst
+                    | DefKind::InlineConst
                     | DefKind::AssocConst
             ),
         "Unexpected DefKind: {:?}",
index 80551518d3c5d8bdbe10341d2fd5d98e8ec1dafb..821b048eb9bcfc80331ce6f46616bcd3b42babc1 100644 (file)
@@ -51,10 +51,8 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
         // If the function itself is not annotated with `const`, it may still be a `const fn`
         // if it resides in a const trait impl.
         is_parent_const_impl_raw(tcx, hir_id)
-    } else if let hir::Node::Ctor(_) = node {
-        true
     } else {
-        false
+        matches!(node, hir::Node::Ctor(_))
     }
 }
 
index a7012cd63f313059b270808ebea4cc8fe6d16c8d..5b4a5ac3577224722763b872f6ede27acbac6b2d 100644 (file)
@@ -138,10 +138,8 @@ fn path_generic_args(
         args: &[GenericArg<'tcx>],
     ) -> Result<Self::Path, Self::Error> {
         self = print_prefix(self)?;
-        let args = args.iter().cloned().filter(|arg| match arg.unpack() {
-            GenericArgKind::Lifetime(_) => false,
-            _ => true,
-        });
+        let args =
+            args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
         if args.clone().next().is_some() {
             self.generic_delimiters(|cx| cx.comma_sep(args))
         } else {
index 323e102b8723b904e8deadc005f055d421b139ec..51207828935d231b2e54b20898c82a4d49654f5d 100644 (file)
@@ -131,6 +131,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Whether to enforce the validity invariant
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
+    /// Whether to enforce validity (e.g., initialization and not having ptr provenance)
+    /// of integers and floats.
+    fn enforce_number_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+
     /// Whether function calls should be [ABI](Abi)-checked.
     fn enforce_abi(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         true
@@ -426,6 +430,11 @@ fn enforce_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
         false // for now, we don't enforce validity
     }
 
+    #[inline(always)]
+    fn enforce_number_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
+        true
+    }
+
     #[inline(always)]
     fn call_extra_fn(
         _ecx: &mut InterpCx<$mir, $tcx, Self>,
index 8d3544d434acf8560f81ab6b544ae1fe121e271d..00208574c555e9b77207dbb063a7041b2fba3427 100644 (file)
@@ -345,10 +345,8 @@ pub(crate) fn eval_fn_call(
 
                     // Figure out how to pass which arguments.
                     // The Rust ABI is special: ZST get skipped.
-                    let rust_abi = match caller_abi {
-                        Abi::Rust | Abi::RustCall => true,
-                        _ => false,
-                    };
+                    let rust_abi = matches!(caller_abi, Abi::Rust | Abi::RustCall);
+
                     // We have two iterators: Where the arguments come from,
                     // and where they go to.
 
index fc69770bf6a306f68bd89aa3f2ff60005507b4e2..6be3e19a833f49daeb93032188f70a11d8331693 100644 (file)
@@ -520,7 +520,7 @@ fn try_visit_primitive(
                 let value = self.read_scalar(value)?;
                 // NOTE: Keep this in sync with the array optimization for int/float
                 // types below!
-                if self.ctfe_mode.is_some() {
+                if M::enforce_number_validity(self.ecx) {
                     // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
                     let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok());
                     if !is_bits {
@@ -528,9 +528,6 @@ fn try_visit_primitive(
                             { "{}", value } expected { "initialized plain (non-pointer) bytes" }
                         )
                     }
-                } else {
-                    // At run-time, for now, we accept *anything* for these types, including
-                    // uninit. We should fix that, but let's start low.
                 }
                 Ok(true)
             }
@@ -855,9 +852,10 @@ fn visit_aggregate(
                     }
                 };
 
+                let allow_uninit_and_ptr = !M::enforce_number_validity(self.ecx);
                 match alloc.check_bytes(
                     alloc_range(Size::ZERO, size),
-                    /*allow_uninit_and_ptr*/ self.ctfe_mode.is_none(),
+                    allow_uninit_and_ptr,
                 ) {
                     // In the happy case, we needn't check anything else.
                     Ok(()) => {}
index 4420c1758a4c5a4a57d9f8ed66fe124bc96e50af..2854e6fd396c243ba358eaa169efff7692dccce8 100644 (file)
@@ -131,10 +131,7 @@ fn in_return_place(
             .body
             .basic_blocks()
             .iter_enumerated()
-            .find(|(_, block)| match block.terminator().kind {
-                TerminatorKind::Return => true,
-                _ => false,
-            })
+            .find(|(_, block)| matches!(block.terminator().kind, TerminatorKind::Return))
             .map(|(bb, _)| bb);
 
         let return_block = match return_block {
@@ -1063,8 +1060,9 @@ fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId)
         let mut fulfillment_cx = traits::FulfillmentContext::new();
         let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span));
         fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause);
-        if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(&err, None, false);
+        let errors = fulfillment_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
         }
     });
 }
index 0fdb772c262dddbbe774fa948551a5c1a5e9e565..abc5a3c6a5206b352fe017a1f5dbef97b286d265 100644 (file)
@@ -170,11 +170,12 @@ fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool {
             let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
             selcx.select(&obligation)
         });
-        match implsrc {
-            Ok(Some(ImplSource::ConstDrop(_)))
-            | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
-            _ => true,
-        }
+        !matches!(
+            implsrc,
+            Ok(Some(
+                ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
+            ))
+        )
     }
 
     fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
index a1ffbae8b15f6dd7d3c02264ade7a1c2faf2d24d..a3ece6550473cce4ce080bbdc5e28f15b69e1cc2 100644 (file)
@@ -34,7 +34,7 @@ pub fn new(value: T) -> Self {
     #[track_caller]
     pub fn borrow(&self) -> MappedReadGuard<'_, T> {
         let borrow = self.value.borrow();
-        if let None = &*borrow {
+        if borrow.is_none() {
             panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
         }
         ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
index 9a57ec991444ac8e160ae835d213b6513afad26e..09fe3a552a0a624df7a317ffef7209f6a0b91ca2 100644 (file)
@@ -267,6 +267,7 @@ fn run_compiler(
                         None,
                         compiler.output_dir(),
                         compiler.output_file(),
+                        compiler.temps_dir(),
                     );
 
                     if should_stop == Compilation::Stop {
@@ -295,6 +296,7 @@ fn run_compiler(
             Some(compiler.input()),
             compiler.output_dir(),
             compiler.output_file(),
+            compiler.temps_dir(),
         )
         .and_then(|| {
             RustcDefaultCalls::list_metadata(
@@ -647,6 +649,7 @@ fn print_crate_info(
         input: Option<&Input>,
         odir: &Option<PathBuf>,
         ofile: &Option<PathBuf>,
+        temps_dir: &Option<PathBuf>,
     ) -> Compilation {
         use rustc_session::config::PrintRequest::*;
         // PrintRequest::NativeStaticLibs is special - printed during linking
@@ -685,7 +688,7 @@ fn print_crate_info(
                     });
                     let attrs = attrs.as_ref().unwrap();
                     let t_outputs = rustc_interface::util::build_output_filenames(
-                        input, odir, ofile, attrs, sess,
+                        input, odir, ofile, temps_dir, attrs, sess,
                     );
                     let id = rustc_session::output::find_crate_name(sess, attrs, input);
                     if *req == PrintRequest::CrateName {
index 42ce849c64d6a1ec14ea677c021006bd7c5660d8..ce26ff62235f466103df17ccdf0b1e07287460d6 100644 (file)
 E0783: include_str!("./error_codes/E0783.md"),
 E0784: include_str!("./error_codes/E0784.md"),
 E0785: include_str!("./error_codes/E0785.md"),
+E0786: include_str!("./error_codes/E0786.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
index da53b671ad0cc8e6b57359faa0f3c9cf12eda9d5..4405a2149ceb80c12bd21033e34709d18da82efd 100644 (file)
@@ -4,15 +4,12 @@ enum.
 Erroneous code example:
 
 ```compile_fail,E0206
-type Foo = [u8; 256];
-impl Copy for Foo { } // error!
-
 #[derive(Copy, Clone)]
 struct Bar;
 
 impl Copy for &'static mut Bar { } // error!
 ```
 
-You can only implement `Copy` for a struct or an enum. Both of the previous
-examples will fail, because neither `[u8; 256]` nor `&'static mut Bar`
-(mutable reference to `Bar`) is a struct or enum.
+You can only implement `Copy` for a struct or an enum.
+The previous example will fail because `&'static mut Bar`
+is not a struct or enum.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0786.md b/compiler/rustc_error_codes/src/error_codes/E0786.md
new file mode 100644 (file)
index 0000000..4a9635b
--- /dev/null
@@ -0,0 +1,14 @@
+A metadata file was invalid.
+
+Erroneous code example:
+
+```ignore (needs extern files)
+use ::foo; // error: found invalid metadata files for crate `foo`
+```
+
+When loading crates, each crate must have a valid metadata file.
+Invalid files could be caused by filesystem corruption,
+an IO error while reading the file, or (rarely) a bug in the compiler itself.
+
+Consider deleting the file and recreating it,
+or reporting a bug against the compiler.
index 1eb497460e63c053ceec0ea015227513c0dfa79a..9db8f751390c110d3993b4468585211540e1c68d 100644 (file)
@@ -66,7 +66,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
 /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
 fn annotation_type_for_level(level: Level) -> AnnotationType {
     match level {
-        Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
+        Level::Bug | Level::Fatal | Level::Error { .. } => AnnotationType::Error,
         Level::Warning => AnnotationType::Warning,
         Level::Note => AnnotationType::Note,
         Level::Help => AnnotationType::Help,
index f2381d75c565fd6d365edf242f363b44c0836722..e5116cd8dfed2c1b7ff840ec2a218900935fa620 100644 (file)
@@ -114,7 +114,7 @@ pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) ->
 
     pub fn is_error(&self) -> bool {
         match self.level {
-            Level::Bug | Level::Fatal | Level::Error | Level::FailureNote => true,
+            Level::Bug | Level::Fatal | Level::Error { .. } | Level::FailureNote => true,
 
             Level::Warning | Level::Note | Level::Help | Level::Cancelled | Level::Allow => false,
         }
index b6cf332f511ec2fe39e4eda5fbbd5982d92539a6..21a2eb771c8e2b7c282c5f0445bc38c9a4c0b632 100644 (file)
@@ -411,6 +411,8 @@ pub struct Handler {
 /// as well as inconsistent state observation.
 struct HandlerInner {
     flags: HandlerFlags,
+    /// The number of lint errors that have been emitted.
+    lint_err_count: usize,
     /// The number of errors that have been emitted, including duplicates.
     ///
     /// This is not necessarily the count that's reported to the user once
@@ -550,6 +552,7 @@ pub fn with_emitter_and_flags(
             flags,
             inner: Lock::new(HandlerInner {
                 flags,
+                lint_err_count: 0,
                 err_count: 0,
                 warn_count: 0,
                 deduplicated_err_count: 0,
@@ -726,7 +729,13 @@ pub fn struct_span_err_with_code(
     /// Construct a builder at the `Error` level with the `msg`.
     // FIXME: This method should be removed (every error should have an associated error code).
     pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
-        DiagnosticBuilder::new(self, Level::Error, msg)
+        DiagnosticBuilder::new(self, Level::Error { lint: false }, msg)
+    }
+
+    /// This should only be used by `rustc_middle::lint::struct_lint_level`. Do not use it for hard errors.
+    #[doc(hidden)]
+    pub fn struct_err_lint(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        DiagnosticBuilder::new(self, Level::Error { lint: true }, msg)
     }
 
     /// Construct a builder at the `Error` level with the `msg` and the `code`.
@@ -790,11 +799,14 @@ pub fn span_fatal_with_code(
     }
 
     pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
-        self.emit_diag_at_span(Diagnostic::new(Error, msg), span);
+        self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span);
     }
 
     pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
-        self.emit_diag_at_span(Diagnostic::new_with_code(Error, Some(code), msg), span);
+        self.emit_diag_at_span(
+            Diagnostic::new_with_code(Error { lint: false }, Some(code), msg),
+            span,
+        );
     }
 
     pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: &str) {
@@ -862,6 +874,9 @@ pub fn err_count(&self) -> usize {
     pub fn has_errors(&self) -> bool {
         self.inner.borrow().has_errors()
     }
+    pub fn has_errors_or_lint_errors(&self) -> bool {
+        self.inner.borrow().has_errors_or_lint_errors()
+    }
     pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.inner.borrow().has_errors_or_delayed_span_bugs()
     }
@@ -979,7 +994,11 @@ fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
             }
         }
         if diagnostic.is_error() {
-            self.bump_err_count();
+            if matches!(diagnostic.level, Level::Error { lint: true }) {
+                self.bump_lint_err_count();
+            } else {
+                self.bump_err_count();
+            }
         } else {
             self.bump_warn_count();
         }
@@ -1073,11 +1092,14 @@ fn err_count(&self) -> usize {
     fn has_errors(&self) -> bool {
         self.err_count() > 0
     }
+    fn has_errors_or_lint_errors(&self) -> bool {
+        self.has_errors() || self.lint_err_count > 0
+    }
     fn has_errors_or_delayed_span_bugs(&self) -> bool {
         self.has_errors() || !self.delayed_span_bugs.is_empty()
     }
     fn has_any_message(&self) -> bool {
-        self.err_count() > 0 || self.warn_count > 0
+        self.err_count() > 0 || self.lint_err_count > 0 || self.warn_count > 0
     }
 
     fn abort_if_errors(&mut self) {
@@ -1131,7 +1153,7 @@ fn fatal(&mut self, msg: &str) -> FatalError {
     }
 
     fn err(&mut self, msg: &str) {
-        self.emit_error(Error, msg);
+        self.emit_error(Error { lint: false }, msg);
     }
 
     /// Emit an error; level should be `Error` or `Fatal`.
@@ -1167,6 +1189,11 @@ fn flush_delayed(&mut self, bugs: Vec<Diagnostic>, explanation: &str) {
         }
     }
 
+    fn bump_lint_err_count(&mut self) {
+        self.lint_err_count += 1;
+        self.panic_if_treat_err_as_bug();
+    }
+
     fn bump_err_count(&mut self) {
         self.err_count += 1;
         self.panic_if_treat_err_as_bug();
@@ -1210,7 +1237,10 @@ fn decorate(mut self) -> Diagnostic {
 pub enum Level {
     Bug,
     Fatal,
-    Error,
+    Error {
+        /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
+        lint: bool,
+    },
     Warning,
     Note,
     Help,
@@ -1229,7 +1259,7 @@ impl Level {
     fn color(self) -> ColorSpec {
         let mut spec = ColorSpec::new();
         match self {
-            Bug | Fatal | Error => {
+            Bug | Fatal | Error { .. } => {
                 spec.set_fg(Some(Color::Red)).set_intense(true);
             }
             Warning => {
@@ -1250,7 +1280,7 @@ fn color(self) -> ColorSpec {
     pub fn to_str(self) -> &'static str {
         match self {
             Bug => "error: internal compiler error",
-            Fatal | Error => "error",
+            Fatal | Error { .. } => "error",
             Warning => "warning",
             Note => "note",
             Help => "help",
index 3f84979ac05e762bbc26b4bd404c52b2352356a2..42c17a60a5d4e1b25e73bb5cf043c49bb72cea6b 100644 (file)
@@ -24,8 +24,9 @@ fn expand<'cx>(
         span: Span,
         input: TokenStream,
     ) -> Result<TokenStream, ErrorReported> {
+        let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
         let server = proc_macro_server::Rustc::new(ecx);
-        self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| {
+        self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| {
             let mut err = ecx.struct_span_err(span, "proc macro panicked");
             if let Some(s) = e.as_str() {
                 err.help(&format!("message: {}", s));
@@ -48,9 +49,10 @@ fn expand<'cx>(
         annotation: TokenStream,
         annotated: TokenStream,
     ) -> Result<TokenStream, ErrorReported> {
+        let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
         let server = proc_macro_server::Rustc::new(ecx);
         self.client
-            .run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace)
+            .run(&EXEC_STRATEGY, server, annotation, annotated, proc_macro_backtrace)
             .map_err(|e| {
                 let mut err = ecx.struct_span_err(span, "custom attribute panicked");
                 if let Some(s) = e.as_str() {
@@ -97,19 +99,19 @@ fn expand(
             nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No)
         };
 
+        let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
         let server = proc_macro_server::Rustc::new(ecx);
-        let stream =
-            match self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace) {
-                Ok(stream) => stream,
-                Err(e) => {
-                    let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
-                    if let Some(s) = e.as_str() {
-                        err.help(&format!("message: {}", s));
-                    }
-                    err.emit();
-                    return ExpandResult::Ready(vec![]);
+        let stream = match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) {
+            Ok(stream) => stream,
+            Err(e) => {
+                let mut err = ecx.struct_span_err(span, "proc-macro derive panicked");
+                if let Some(s) = e.as_str() {
+                    err.help(&format!("message: {}", s));
                 }
-            };
+                err.emit();
+                return ExpandResult::Ready(vec![]);
+            }
+        };
 
         let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count();
         let mut parser =
index 5cb97198765fe4411a8e691f1990e7e9e2a850c6..fa9e98be9e881f6b0c1bdd51aa4dae4e784a2319 100644 (file)
@@ -1,4 +1,4 @@
-use crate::base::{ExtCtxt, ResolverExpand};
+use crate::base::ExtCtxt;
 
 use rustc_ast as ast;
 use rustc_ast::token::{self, Nonterminal, NtIdent};
@@ -7,7 +7,7 @@
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::Diagnostic;
+use rustc_errors::{Diagnostic, PResult};
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::lexer::nfc_normalize;
@@ -53,11 +53,11 @@ fn to_internal(self) -> token::DelimToken {
     }
 }
 
-impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_>)>
+impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)>
     for TokenTree<Group, Punct, Ident, Literal>
 {
     fn from_internal(
-        ((tree, spacing), stack, rustc): (TreeAndSpacing, &mut Vec<Self>, &mut Rustc<'_>),
+        ((tree, spacing), stack, rustc): (TreeAndSpacing, &mut Vec<Self>, &mut Rustc<'_, '_>),
     ) -> Self {
         use rustc_ast::token::*;
 
@@ -146,10 +146,10 @@ macro_rules! op {
             SingleQuote => op!('\''),
 
             Ident(name, false) if name == kw::DollarCrate => tt!(Ident::dollar_crate()),
-            Ident(name, is_raw) => tt!(Ident::new(rustc.sess, name, is_raw)),
+            Ident(name, is_raw) => tt!(Ident::new(rustc.sess(), name, is_raw)),
             Lifetime(name) => {
                 let ident = symbol::Ident::new(name, span).without_first_quote();
-                stack.push(tt!(Ident::new(rustc.sess, ident.name, false)));
+                stack.push(tt!(Ident::new(rustc.sess(), ident.name, false)));
                 tt!(Punct::new('\'', true))
             }
             Literal(lit) => tt!(Literal { lit }),
@@ -181,15 +181,15 @@ macro_rules! op {
             Interpolated(nt)
                 if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, rustc) =>
             {
-                TokenTree::Ident(Ident::new(rustc.sess, name.name, is_raw, name.span))
+                TokenTree::Ident(Ident::new(rustc.sess(), name.name, is_raw, name.span))
             }
             Interpolated(nt) => {
-                let stream = nt_to_tokenstream(&nt, rustc.sess, CanSynthesizeMissingTokens::No);
+                let stream = nt_to_tokenstream(&nt, rustc.sess(), CanSynthesizeMissingTokens::No);
                 TokenTree::Group(Group {
                     delimiter: Delimiter::None,
                     stream,
                     span: DelimSpan::from_single(span),
-                    flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess),
+                    flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess()),
                 })
             }
 
@@ -273,7 +273,7 @@ fn to_internal(self) -> TokenStream {
 impl ToInternal<rustc_errors::Level> for Level {
     fn to_internal(self) -> rustc_errors::Level {
         match self {
-            Level::Error => rustc_errors::Level::Error,
+            Level::Error => rustc_errors::Level::Error { lint: false },
             Level::Warning => rustc_errors::Level::Warning,
             Level::Note => rustc_errors::Level::Note,
             Level::Help => rustc_errors::Level::Help,
@@ -355,38 +355,38 @@ pub struct Literal {
     span: Span,
 }
 
-pub(crate) struct Rustc<'a> {
-    resolver: &'a dyn ResolverExpand,
-    sess: &'a ParseSess,
+pub(crate) struct Rustc<'a, 'b> {
+    ecx: &'a mut ExtCtxt<'b>,
     def_site: Span,
     call_site: Span,
     mixed_site: Span,
-    span_debug: bool,
     krate: CrateNum,
     rebased_spans: FxHashMap<usize, Span>,
 }
 
-impl<'a> Rustc<'a> {
-    pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
-        let expn_data = cx.current_expansion.id.expn_data();
+impl<'a, 'b> Rustc<'a, 'b> {
+    pub fn new(ecx: &'a mut ExtCtxt<'b>) -> Self {
+        let expn_data = ecx.current_expansion.id.expn_data();
         Rustc {
-            resolver: cx.resolver,
-            sess: cx.parse_sess(),
-            def_site: cx.with_def_site_ctxt(expn_data.def_site),
-            call_site: cx.with_call_site_ctxt(expn_data.call_site),
-            mixed_site: cx.with_mixed_site_ctxt(expn_data.call_site),
-            span_debug: cx.ecfg.span_debug,
+            def_site: ecx.with_def_site_ctxt(expn_data.def_site),
+            call_site: ecx.with_call_site_ctxt(expn_data.call_site),
+            mixed_site: ecx.with_mixed_site_ctxt(expn_data.call_site),
             krate: expn_data.macro_def_id.unwrap().krate,
             rebased_spans: FxHashMap::default(),
+            ecx,
         }
     }
 
+    fn sess(&self) -> &ParseSess {
+        self.ecx.parse_sess()
+    }
+
     fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Literal {
         Literal { lit: token::Lit::new(kind, symbol, suffix), span: server::Span::call_site(self) }
     }
 }
 
-impl server::Types for Rustc<'_> {
+impl server::Types for Rustc<'_, '_> {
     type FreeFunctions = FreeFunctions;
     type TokenStream = TokenStream;
     type TokenStreamBuilder = tokenstream::TokenStreamBuilder;
@@ -401,17 +401,20 @@ impl server::Types for Rustc<'_> {
     type Span = Span;
 }
 
-impl server::FreeFunctions for Rustc<'_> {
+impl server::FreeFunctions for Rustc<'_, '_> {
     fn track_env_var(&mut self, var: &str, value: Option<&str>) {
-        self.sess.env_depinfo.borrow_mut().insert((Symbol::intern(var), value.map(Symbol::intern)));
+        self.sess()
+            .env_depinfo
+            .borrow_mut()
+            .insert((Symbol::intern(var), value.map(Symbol::intern)));
     }
 
     fn track_path(&mut self, path: &str) {
-        self.sess.file_depinfo.borrow_mut().insert(Symbol::intern(path));
+        self.sess().file_depinfo.borrow_mut().insert(Symbol::intern(path));
     }
 }
 
-impl server::TokenStream for Rustc<'_> {
+impl server::TokenStream for Rustc<'_, '_> {
     fn new(&mut self) -> Self::TokenStream {
         TokenStream::default()
     }
@@ -422,13 +425,62 @@ fn from_str(&mut self, src: &str) -> Self::TokenStream {
         parse_stream_from_source_str(
             FileName::proc_macro_source_code(src),
             src.to_string(),
-            self.sess,
+            self.sess(),
             Some(self.call_site),
         )
     }
     fn to_string(&mut self, stream: &Self::TokenStream) -> String {
         pprust::tts_to_string(stream)
     }
+    fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
+        // Parse the expression from our tokenstream.
+        let expr: PResult<'_, _> = try {
+            let mut p = rustc_parse::stream_to_parser(
+                self.sess(),
+                stream.clone(),
+                Some("proc_macro expand expr"),
+            );
+            let expr = p.parse_expr()?;
+            if p.token != token::Eof {
+                p.unexpected()?;
+            }
+            expr
+        };
+        let expr = expr.map_err(|mut err| err.emit())?;
+
+        // Perform eager expansion on the expression.
+        let expr = self
+            .ecx
+            .expander()
+            .fully_expand_fragment(crate::expand::AstFragment::Expr(expr))
+            .make_expr();
+
+        // NOTE: For now, limit `expand_expr` to exclusively expand to literals.
+        // This may be relaxed in the future.
+        // We don't use `nt_to_tokenstream` as the tokenstream currently cannot
+        // be recovered in the general case.
+        match &expr.kind {
+            ast::ExprKind::Lit(l) => {
+                Ok(tokenstream::TokenTree::token(token::Literal(l.token), l.span).into())
+            }
+            ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
+                ast::ExprKind::Lit(l) => match l.token {
+                    token::Lit { kind: token::Integer | token::Float, .. } => {
+                        Ok(std::array::IntoIter::new([
+                            // FIXME: The span of the `-` token is lost when
+                            // parsing, so we cannot faithfully recover it here.
+                            tokenstream::TokenTree::token(token::BinOp(token::Minus), e.span),
+                            tokenstream::TokenTree::token(token::Literal(l.token), l.span),
+                        ])
+                        .collect())
+                    }
+                    _ => Err(()),
+                },
+                _ => Err(()),
+            },
+            _ => Err(()),
+        }
+    }
     fn from_token_tree(
         &mut self,
         tree: TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
@@ -440,7 +492,7 @@ fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
     }
 }
 
-impl server::TokenStreamBuilder for Rustc<'_> {
+impl server::TokenStreamBuilder for Rustc<'_, '_> {
     fn new(&mut self) -> Self::TokenStreamBuilder {
         tokenstream::TokenStreamBuilder::new()
     }
@@ -452,7 +504,7 @@ fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
     }
 }
 
-impl server::TokenStreamIter for Rustc<'_> {
+impl server::TokenStreamIter for Rustc<'_, '_> {
     fn next(
         &mut self,
         iter: &mut Self::TokenStreamIter,
@@ -477,7 +529,7 @@ fn next(
     }
 }
 
-impl server::Group for Rustc<'_> {
+impl server::Group for Rustc<'_, '_> {
     fn new(&mut self, delimiter: Delimiter, stream: Self::TokenStream) -> Self::Group {
         Group {
             delimiter,
@@ -506,7 +558,7 @@ fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
     }
 }
 
-impl server::Punct for Rustc<'_> {
+impl server::Punct for Rustc<'_, '_> {
     fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
         Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
     }
@@ -524,9 +576,9 @@ fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
     }
 }
 
-impl server::Ident for Rustc<'_> {
+impl server::Ident for Rustc<'_, '_> {
     fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
-        Ident::new(self.sess, Symbol::intern(string), is_raw, span)
+        Ident::new(self.sess(), Symbol::intern(string), is_raw, span)
     }
     fn span(&mut self, ident: Self::Ident) -> Self::Span {
         ident.span
@@ -536,10 +588,10 @@ fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
     }
 }
 
-impl server::Literal for Rustc<'_> {
+impl server::Literal for Rustc<'_, '_> {
     fn from_str(&mut self, s: &str) -> Result<Self::Literal, ()> {
         let name = FileName::proc_macro_source_code(s);
-        let mut parser = rustc_parse::new_parser_from_source_str(self.sess, name, s.to_owned());
+        let mut parser = rustc_parse::new_parser_from_source_str(self.sess(), name, s.to_owned());
 
         let first_span = parser.token.span.data();
         let minus_present = parser.eat(&token::BinOp(token::Minus));
@@ -675,7 +727,7 @@ fn subspan(
     }
 }
 
-impl server::SourceFile for Rustc<'_> {
+impl server::SourceFile for Rustc<'_, '_> {
     fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
         Lrc::ptr_eq(file1, file2)
     }
@@ -695,7 +747,7 @@ fn is_real(&mut self, file: &Self::SourceFile) -> bool {
     }
 }
 
-impl server::MultiSpan for Rustc<'_> {
+impl server::MultiSpan for Rustc<'_, '_> {
     fn new(&mut self) -> Self::MultiSpan {
         vec![]
     }
@@ -704,7 +756,7 @@ fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) {
     }
 }
 
-impl server::Diagnostic for Rustc<'_> {
+impl server::Diagnostic for Rustc<'_, '_> {
     fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
         let mut diag = Diagnostic::new(level.to_internal(), msg);
         diag.set_span(MultiSpan::from_spans(spans));
@@ -720,13 +772,13 @@ fn sub(
         diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
     }
     fn emit(&mut self, diag: Self::Diagnostic) {
-        self.sess.span_diagnostic.emit_diagnostic(&diag);
+        self.sess().span_diagnostic.emit_diagnostic(&diag);
     }
 }
 
-impl server::Span for Rustc<'_> {
+impl server::Span for Rustc<'_, '_> {
     fn debug(&mut self, span: Self::Span) -> String {
-        if self.span_debug {
+        if self.ecx.ecfg.span_debug {
             format!("{:?}", span)
         } else {
             format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
@@ -742,7 +794,7 @@ fn mixed_site(&mut self) -> Self::Span {
         self.mixed_site
     }
     fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
-        self.sess.source_map().lookup_char_pos(span.lo()).file
+        self.sess().source_map().lookup_char_pos(span.lo()).file
     }
     fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
         span.parent_callsite()
@@ -751,11 +803,11 @@ fn source(&mut self, span: Self::Span) -> Self::Span {
         span.source_callsite()
     }
     fn start(&mut self, span: Self::Span) -> LineColumn {
-        let loc = self.sess.source_map().lookup_char_pos(span.lo());
+        let loc = self.sess().source_map().lookup_char_pos(span.lo());
         LineColumn { line: loc.line, column: loc.col.to_usize() }
     }
     fn end(&mut self, span: Self::Span) -> LineColumn {
-        let loc = self.sess.source_map().lookup_char_pos(span.hi());
+        let loc = self.sess().source_map().lookup_char_pos(span.hi());
         LineColumn { line: loc.line, column: loc.col.to_usize() }
     }
     fn before(&mut self, span: Self::Span) -> Self::Span {
@@ -765,8 +817,8 @@ fn after(&mut self, span: Self::Span) -> Self::Span {
         span.shrink_to_hi()
     }
     fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
-        let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
-        let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
+        let self_loc = self.sess().source_map().lookup_char_pos(first.lo());
+        let other_loc = self.sess().source_map().lookup_char_pos(second.lo());
 
         if self_loc.file.name != other_loc.file.name {
             return None;
@@ -778,7 +830,7 @@ fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
         span.with_ctxt(at.ctxt())
     }
     fn source_text(&mut self, span: Self::Span) -> Option<String> {
-        self.sess.source_map().span_to_snippet(span).ok()
+        self.sess().source_map().span_to_snippet(span).ok()
     }
     /// Saves the provided span into the metadata of
     /// *the crate we are currently compiling*, which must
@@ -805,10 +857,10 @@ fn source_text(&mut self, span: Self::Span) -> Option<String> {
     /// since we've loaded `my_proc_macro` from disk in order to execute it).
     /// In this way, we have obtained a span pointing into `my_proc_macro`
     fn save_span(&mut self, span: Self::Span) -> usize {
-        self.sess.save_proc_macro_span(span)
+        self.sess().save_proc_macro_span(span)
     }
     fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
-        let (resolver, krate, def_site) = (self.resolver, self.krate, self.def_site);
+        let (resolver, krate, def_site) = (&*self.ecx.resolver, self.krate, self.def_site);
         *self.rebased_spans.entry(id).or_insert_with(|| {
             // FIXME: `SyntaxContext` for spans from proc macro crates is lost during encoding,
             // replace it with a def-site context until we are encoding it properly.
@@ -821,11 +873,11 @@ fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
 fn ident_name_compatibility_hack(
     nt: &Nonterminal,
     orig_span: Span,
-    rustc: &mut Rustc<'_>,
+    rustc: &mut Rustc<'_, '_>,
 ) -> Option<(rustc_span::symbol::Ident, bool)> {
     if let NtIdent(ident, is_raw) = nt {
         if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
-            let source_map = rustc.sess.source_map();
+            let source_map = rustc.sess().source_map();
             let filename = source_map.span_to_filename(orig_span);
             if let FileName::Real(RealFileName::LocalPath(path)) = filename {
                 let matches_prefix = |prefix, filename| {
@@ -846,7 +898,7 @@ fn ident_name_compatibility_hack(
                     let snippet = source_map.span_to_snippet(orig_span);
                     if snippet.as_deref() == Ok("$name") {
                         if time_macros_impl {
-                            rustc.sess.buffer_lint_with_diagnostic(
+                            rustc.sess().buffer_lint_with_diagnostic(
                                 &PROC_MACRO_BACK_COMPAT,
                                 orig_span,
                                 ast::CRATE_NODE_ID,
@@ -871,7 +923,7 @@ fn ident_name_compatibility_hack(
                                         .and_then(|c| c.parse::<u32>().ok())
                                         .map_or(false, |v| v < 40)
                                 {
-                                    rustc.sess.buffer_lint_with_diagnostic(
+                                    rustc.sess().buffer_lint_with_diagnostic(
                                         &PROC_MACRO_BACK_COMPAT,
                                         orig_span,
                                         ast::CRATE_NODE_ID,
@@ -894,7 +946,7 @@ fn ident_name_compatibility_hack(
                             source_map.span_to_filename(rustc.def_site)
                         {
                             if macro_path.to_string_lossy().contains("pin-project-internal-0.") {
-                                rustc.sess.buffer_lint_with_diagnostic(
+                                rustc.sess().buffer_lint_with_diagnostic(
                                     &PROC_MACRO_BACK_COMPAT,
                                     orig_span,
                                     ast::CRATE_NODE_ID,
index 58f4e229323ac86019740d8985bd8c98c0c46c0d..d8b4539d831bb8dff367979e48d89be58e149af0 100644 (file)
@@ -689,6 +689,15 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
     (active, doc_auto_cfg, "1.58.0", Some(43781), None),
 
+    /// Allows using `const` operands in inline assembly.
+    (active, asm_const, "1.58.0", Some(72016), None),
+
+    /// Allows using `sym` operands in inline assembly.
+    (active, asm_sym, "1.58.0", Some(72016), None),
+
+    /// Enables experimental inline assembly support for additional architectures.
+    (active, asm_experimental_arch, "1.58.0", Some(72016), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
index 33188d375f5d5e2f333ff8605a5414cf58b796ac..7212bbf38c7f215555ef2a3c086e2b20b3dfaa3d 100644 (file)
@@ -115,16 +115,26 @@ macro_rules! template {
 
 macro_rules! ungated {
     ($attr:ident, $typ:expr, $tpl:expr $(,)?) => {
-        (sym::$attr, $typ, $tpl, Ungated)
+        BuiltinAttribute { name: sym::$attr, type_: $typ, template: $tpl, gate: Ungated }
     };
 }
 
 macro_rules! gated {
     ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => {
-        (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)))
+        BuiltinAttribute {
+            name: sym::$attr,
+            type_: $typ,
+            template: $tpl,
+            gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
+        }
     };
     ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => {
-        (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)))
+        BuiltinAttribute {
+            name: sym::$attr,
+            type_: $typ,
+            template: $tpl,
+            gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
+        }
     };
 }
 
@@ -143,12 +153,12 @@ macro_rules! rustc_attr {
         )
     };
     ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => {
-        (
-            sym::$attr,
-            $typ,
-            $tpl,
-            Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
-        )
+        BuiltinAttribute {
+            name: sym::$attr,
+            type_: $typ,
+            template: $tpl,
+            gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
+        }
     };
 }
 
@@ -161,7 +171,12 @@ macro_rules! experimental {
 const IMPL_DETAIL: &str = "internal implementation detail";
 const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable";
 
-pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate);
+pub struct BuiltinAttribute {
+    pub name: Symbol,
+    pub type_: AttributeType,
+    pub template: AttributeTemplate,
+    pub gate: AttributeGate,
+}
 
 /// Attributes that have a special meaning to rustc or rustdoc.
 #[rustfmt::skip]
@@ -290,9 +305,11 @@ macro_rules! experimental {
     ),
 
     // Plugins:
-    (
-        sym::plugin, CrateLevel, template!(List: "name"),
-        Gated(
+    BuiltinAttribute {
+        name: sym::plugin,
+        type_: CrateLevel,
+        template: template!(List: "name"),
+        gate: Gated(
             Stability::Deprecated(
                 "https://github.com/rust-lang/rust/pull/64675",
                 Some("may be removed in a future compiler version"),
@@ -300,8 +317,8 @@ macro_rules! experimental {
             sym::plugin,
             "compiler plugins are deprecated",
             cfg_fn!(plugin)
-        )
-    ),
+        ),
+    },
 
     // Testing:
     gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)),
@@ -497,17 +514,17 @@ macro_rules! experimental {
         lang, Normal, template!(NameValueStr: "name"), lang_items,
         "language items are subject to change",
     ),
-    (
-        sym::rustc_diagnostic_item,
-        Normal,
-        template!(NameValueStr: "name"),
-        Gated(
+    BuiltinAttribute {
+        name: sym::rustc_diagnostic_item,
+        type_: Normal,
+        template: template!(NameValueStr: "name"),
+        gate: Gated(
             Stability::Unstable,
             sym::rustc_attrs,
             "diagnostic items compiler internal support for linting",
             cfg_fn!(rustc_attrs),
         ),
-    ),
+    },
     gated!(
         // Used in resolve:
         prelude_import, Normal, template!(Word),
@@ -601,7 +618,7 @@ macro_rules! experimental {
 ];
 
 pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> {
-    BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect()
+    BUILTIN_ATTRIBUTES.iter().filter(|attr| attr.gate.is_deprecated()).collect()
 }
 
 pub fn is_builtin_attr_name(name: Symbol) -> bool {
@@ -612,8 +629,8 @@ pub fn is_builtin_attr_name(name: Symbol) -> bool {
     SyncLazy::new(|| {
         let mut map = FxHashMap::default();
         for attr in BUILTIN_ATTRIBUTES.iter() {
-            if map.insert(attr.0, attr).is_some() {
-                panic!("duplicate builtin attribute `{}`", attr.0);
+            if map.insert(attr.name, attr).is_some() {
+                panic!("duplicate builtin attribute `{}`", attr.name);
             }
         }
         map
index cb668eb35e093da9b2194eef756f4208e436c677..60761a05de8270180810ca2d6995fab17eb59dac 100644 (file)
@@ -104,8 +104,10 @@ pub enum DefKind {
     Use,
     /// An `extern` block.
     ForeignMod,
-    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`, or `const { 1 + 2}`
+    /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`
     AnonConst,
+    /// An inline constant, e.g. `const { 1 + 2 }`
+    InlineConst,
     /// Opaque type, aka `impl Trait`.
     OpaqueTy,
     Field,
@@ -155,6 +157,7 @@ pub fn descr(self, def_id: DefId) -> &'static str {
             DefKind::Use => "import",
             DefKind::ForeignMod => "foreign module",
             DefKind::AnonConst => "constant expression",
+            DefKind::InlineConst => "inline constant",
             DefKind::Field => "field",
             DefKind::Impl => "implementation",
             DefKind::Closure => "closure",
@@ -174,6 +177,7 @@ pub fn article(&self) -> &'static str {
             | DefKind::OpaqueTy
             | DefKind::Impl
             | DefKind::Use
+            | DefKind::InlineConst
             | DefKind::ExternCrate => "an",
             DefKind::Macro(macro_kind) => macro_kind.article(),
             _ => "a",
@@ -207,6 +211,7 @@ pub fn ns(&self) -> Option<Namespace> {
 
             // Not namespaced.
             DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::Field
             | DefKind::LifetimeParam
             | DefKind::ExternCrate
index 38cbf5314ef314361e3bf869a9a99a9ebf37c1c5..c0137fc7a5ac8da8b0d8c4976f88401a7c2cc7c6 100644 (file)
@@ -139,9 +139,6 @@ pub fn dep_graph_path(sess: &Session) -> PathBuf {
 pub fn staging_dep_graph_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME)
 }
-pub fn dep_graph_path_from(incr_comp_session_dir: &Path) -> PathBuf {
-    in_incr_comp_dir(incr_comp_session_dir, DEP_GRAPH_FILENAME)
-}
 
 pub fn work_products_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME)
index 4d38556e5d2145aa4ee34f275b88b6f4a739d368..5f5e83774dad803882b6cfc528297062d9797007 100644 (file)
@@ -105,7 +105,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
 
     // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`.
     // Fortunately, we just checked that this isn't the case.
-    let path = dep_graph_path_from(&sess.incr_comp_session_dir());
+    let path = dep_graph_path(&sess);
     let report_incremental_info = sess.opts.debugging_opts.incremental_info;
     let expected_hash = sess.opts.dep_tracking_hash(false);
 
index 2296cc6129ae8594a70f579b546d307a844418ad..5b4a9d9dfad456e43b201933ffe15107eb2f73d9 100644 (file)
@@ -108,7 +108,7 @@ fn make_query_response<T>(
         let tcx = self.tcx;
 
         // Select everything, returning errors.
-        let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new);
+        let true_errors = fulfill_cx.select_where_possible(self);
         debug!("true_errors = {:#?}", true_errors);
 
         if !true_errors.is_empty() {
@@ -118,7 +118,7 @@ fn make_query_response<T>(
         }
 
         // Anything left unselected *now* must be an ambiguity.
-        let ambig_errors = fulfill_cx.select_all_or_error(self).err().unwrap_or_else(Vec::new);
+        let ambig_errors = fulfill_cx.select_all_or_error(self);
         debug!("ambig_errors = {:#?}", ambig_errors);
 
         let region_obligations = self.take_registered_region_obligations();
index 2173ff1f9ab035823c013e08abc3d757ea9602d3..298346c373e54cfd9d9a3fc0457556b8f745c99b 100644 (file)
@@ -1466,7 +1466,7 @@ fn add_labels_for_types(
                     let mut returned_async_output_error = false;
                     for &sp in values {
                         if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error {
-                            if &[sp] != err.span.primary_spans() {
+                            if [sp] != err.span.primary_spans() {
                                 let mut span: MultiSpan = sp.into();
                                 span.push_span_label(
                                     sp,
@@ -2190,14 +2190,12 @@ pub fn construct_generic_bound_failure(
 
         if let Some(SubregionOrigin::CompareImplMethodObligation {
             span,
-            item_name,
             impl_item_def_id,
             trait_item_def_id,
         }) = origin
         {
             return self.report_extra_impl_obligation(
                 span,
-                item_name,
                 impl_item_def_id,
                 trait_item_def_id,
                 &format!("`{}: {}`", bound_kind, sub),
index b9e7ee12bc86df55872e82a103729820232a1483..cfa79213c805ce683e5f524bda74e7de27e14629 100644 (file)
@@ -54,12 +54,16 @@ pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorRepo
         {
             if let SubregionOrigin::CompareImplTypeObligation {
                 span,
-                item_name,
                 impl_item_def_id,
                 trait_item_def_id,
             } = origin
             {
-                self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
+                self.emit_associated_type_err(
+                    span,
+                    self.infcx.tcx.item_name(impl_item_def_id),
+                    impl_item_def_id,
+                    trait_item_def_id,
+                );
                 return Some(ErrorReported);
             }
         }
index 167a8893a11c88aded07e7fac752865577cd5816..6600c18351fbe8bdf7628ce5e7938e000880b673 100644 (file)
@@ -330,30 +330,21 @@ pub(super) fn report_concrete_failure(
                 );
                 err
             }
-            infer::CompareImplMethodObligation {
-                span,
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-            } => self.report_extra_impl_obligation(
-                span,
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-                &format!("`{}: {}`", sup, sub),
-            ),
-            infer::CompareImplTypeObligation {
-                span,
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-            } => self.report_extra_impl_obligation(
-                span,
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-                &format!("`{}: {}`", sup, sub),
-            ),
+            infer::CompareImplMethodObligation { span, impl_item_def_id, trait_item_def_id } => {
+                self.report_extra_impl_obligation(
+                    span,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                    &format!("`{}: {}`", sup, sub),
+                )
+            }
+            infer::CompareImplTypeObligation { span, impl_item_def_id, trait_item_def_id } => self
+                .report_extra_impl_obligation(
+                    span,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                    &format!("`{}: {}`", sup, sub),
+                ),
         }
     }
 
index 9dae978dcde7d9b79dd59c74335b6d2529a0684c..32d3db39d64405e6d826ded8999f6425796e1e82 100644 (file)
@@ -419,21 +419,11 @@ pub enum SubregionOrigin<'tcx> {
 
     /// Comparing the signature and requirements of an impl method against
     /// the containing trait.
-    CompareImplMethodObligation {
-        span: Span,
-        item_name: Symbol,
-        impl_item_def_id: DefId,
-        trait_item_def_id: DefId,
-    },
+    CompareImplMethodObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId },
 
     /// Comparing the signature and requirements of an impl associated type
     /// against the containing trait
-    CompareImplTypeObligation {
-        span: Span,
-        item_name: Symbol,
-        impl_item_def_id: DefId,
-        trait_item_def_id: DefId,
-    },
+    CompareImplTypeObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId },
 }
 
 // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -1830,23 +1820,19 @@ pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default:
             }
 
             traits::ObligationCauseCode::CompareImplMethodObligation {
-                item_name,
                 impl_item_def_id,
                 trait_item_def_id,
             } => SubregionOrigin::CompareImplMethodObligation {
                 span: cause.span,
-                item_name,
                 impl_item_def_id,
                 trait_item_def_id,
             },
 
             traits::ObligationCauseCode::CompareImplTypeObligation {
-                item_name,
                 impl_item_def_id,
                 trait_item_def_id,
             } => SubregionOrigin::CompareImplTypeObligation {
                 span: cause.span,
-                item_name,
                 impl_item_def_id,
                 trait_item_def_id,
             },
index 9e04773c5fa2056c9bb4865d9051e938b5a0f86b..3947282aa6217f4dba820c79d75c6596e4294262 100644 (file)
@@ -99,7 +99,7 @@ pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<
     /// function. We can then add implied bounds and the like from the
     /// closure arguments into the environment -- these should only
     /// apply in the closure body, so once we exit, we invoke
-    /// `pop_snapshot_post_closure` to remove them.
+    /// `pop_snapshot_post_typeck_child` to remove them.
     ///
     /// Example:
     ///
@@ -129,12 +129,12 @@ pub fn region_bound_pairs_map(&self) -> &FxHashMap<hir::HirId, RegionBoundPairs<
     /// seems like it'd be readily fixed if we wanted. There are
     /// similar leaks around givens that seem equally suspicious, to
     /// be honest. --nmatsakis
-    pub fn push_snapshot_pre_closure(&self) -> usize {
+    pub fn push_snapshot_pre_typeck_child(&self) -> usize {
         self.region_bound_pairs_accum.len()
     }
 
-    /// See `push_snapshot_pre_closure`.
-    pub fn pop_snapshot_post_closure(&mut self, len: usize) {
+    /// See `push_snapshot_pre_typeck_child`.
+    pub fn pop_snapshot_post_typeck_child(&mut self, len: usize) {
         self.region_bound_pairs_accum.truncate(len);
     }
 
index dce4a87b041189a49910765f763ef7798d781a77..152a395c871be44a6008ba8cb46bd81c9094548a 100644 (file)
@@ -46,30 +46,25 @@ fn register_predicate_obligation(
         obligation: PredicateObligation<'tcx>,
     );
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>>;
 
     fn select_all_with_constness_or_error(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         _constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         self.select_all_or_error(infcx)
     }
 
-    fn select_where_possible(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+    fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>)
+    -> Vec<FulfillmentError<'tcx>>;
 
     // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated
     fn select_with_constness_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         _constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         self.select_where_possible(infcx)
     }
 
index 9dbfa3a850ba848d505e469ac4edf8ee44f33f3b..c1f302e665d4b77cbfffae619a0f05afe49b7168 100644 (file)
@@ -6,7 +6,6 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::symbol::Symbol;
 use rustc_span::{MultiSpan, Span};
 use std::fmt;
 use std::iter;
@@ -15,8 +14,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn report_extra_impl_obligation(
         &self,
         error_span: Span,
-        item_name: Symbol,
-        _impl_item_def_id: DefId,
+        impl_item_def_id: DefId,
         trait_item_def_id: DefId,
         requirement: &dyn fmt::Display,
     ) -> DiagnosticBuilder<'tcx> {
@@ -27,6 +25,7 @@ pub fn report_extra_impl_obligation(
 
         if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
             let span = self.tcx.sess.source_map().guess_head_span(trait_item_span);
+            let item_name = self.tcx.item_name(impl_item_def_id);
             err.span_label(span, format!("definition of `{}` from trait", item_name));
         }
 
index 7a6a643e3d0bb27ed53eb4e764da2f8989dae487..2904b3f5b7071bd5f54ed664a200d1bb0b1ac353 100644 (file)
@@ -36,6 +36,7 @@ pub struct Compiler {
     pub(crate) input_path: Option<PathBuf>,
     pub(crate) output_dir: Option<PathBuf>,
     pub(crate) output_file: Option<PathBuf>,
+    pub(crate) temps_dir: Option<PathBuf>,
     pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
     pub(crate) override_queries:
         Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
@@ -57,6 +58,9 @@ pub fn output_dir(&self) -> &Option<PathBuf> {
     pub fn output_file(&self) -> &Option<PathBuf> {
         &self.output_file
     }
+    pub fn temps_dir(&self) -> &Option<PathBuf> {
+        &self.temps_dir
+    }
     pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> {
         &self.register_lints
     }
@@ -65,7 +69,14 @@ pub fn build_output_filenames(
         sess: &Session,
         attrs: &[ast::Attribute],
     ) -> OutputFilenames {
-        util::build_output_filenames(&self.input, &self.output_dir, &self.output_file, attrs, sess)
+        util::build_output_filenames(
+            &self.input,
+            &self.output_dir,
+            &self.output_file,
+            &self.temps_dir,
+            attrs,
+            sess,
+        )
     }
 }
 
@@ -186,6 +197,8 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
         );
     }
 
+    let temps_dir = sess.opts.debugging_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
+
     let compiler = Compiler {
         sess,
         codegen_backend,
@@ -193,6 +206,7 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
         input_path: config.input_path,
         output_dir: config.output_dir,
         output_file: config.output_file,
+        temps_dir,
         register_lints: config.register_lints,
         override_queries: config.override_queries,
     };
index 62f5f09aa48279a7a1eed4031bd3c858cc11f42d..b073ee9682fbdfeef72fb6c9ad20f0fca95a9184 100644 (file)
@@ -47,7 +47,7 @@
 use std::io::{self, BufWriter, Write};
 use std::lazy::SyncLazy;
 use std::marker::PhantomPinned;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::pin::Pin;
 use std::rc::Rc;
 use std::{env, fs, iter};
@@ -536,7 +536,7 @@ fn check_output<F, T>(output_paths: &[PathBuf], f: F) -> Option<T>
     None
 }
 
-fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool {
+fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool {
     let input_path = input_path.canonicalize().ok();
     if input_path.is_none() {
         return false;
@@ -552,7 +552,7 @@ fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<PathBuf> {
     check_output(output_paths, check)
 }
 
-fn escape_dep_filename(filename: &String) -> String {
+fn escape_dep_filename(filename: &str) -> String {
     // Apparently clang and gcc *only* escape spaces:
     // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
     filename.replace(" ", "\\ ")
@@ -692,6 +692,7 @@ pub fn prepare_outputs(
         &compiler.input,
         &compiler.output_dir,
         &compiler.output_file,
+        &compiler.temps_dir,
         &krate.attrs,
         sess,
     );
@@ -722,6 +723,13 @@ pub fn prepare_outputs(
         }
     }
 
+    if let Some(ref dir) = compiler.temps_dir {
+        if fs::create_dir_all(dir).is_err() {
+            sess.err("failed to find or create the directory specified by `--temps-dir`");
+            return Err(ErrorReported);
+        }
+    }
+
     write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
 
     let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
index 2d3cb52f5fd478fc6718f715765ce8375479f73d..eed2e07e890e72799ad76ad692c4148106dea7ca 100644 (file)
@@ -685,6 +685,7 @@ macro_rules! untracked {
     untracked!(span_debug, true);
     untracked!(span_free_formats, true);
     untracked!(strip, Strip::Debuginfo);
+    untracked!(temps_dir, Some(String::from("abc")));
     untracked!(terminal_width, Some(80));
     untracked!(threads, 99);
     untracked!(time, true);
index cffb087af187f9be0d080b798b90b08dd8e93bba..04e183a9ba57ea944dce65b104efd12871237af1 100644 (file)
@@ -604,6 +604,7 @@ pub fn build_output_filenames(
     input: &Input,
     odir: &Option<PathBuf>,
     ofile: &Option<PathBuf>,
+    temps_dir: &Option<PathBuf>,
     attrs: &[ast::Attribute],
     sess: &Session,
 ) -> OutputFilenames {
@@ -626,6 +627,7 @@ pub fn build_output_filenames(
                 dirpath,
                 stem,
                 None,
+                temps_dir.clone(),
                 sess.opts.cg.extra_filename.clone(),
                 sess.opts.output_types.clone(),
             )
@@ -654,6 +656,7 @@ pub fn build_output_filenames(
                 out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
                 out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(),
                 ofile,
+                temps_dir.clone(),
                 sess.opts.cg.extra_filename.clone(),
                 sess.opts.output_types.clone(),
             )
@@ -776,7 +779,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
     fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
         let is_const = match i {
             ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
-            ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig),
+            ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
             _ => false,
         };
         self.run(is_const, |s| noop_visit_item_kind(i, s))
@@ -785,7 +788,7 @@ fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
     fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let is_const = match i.kind {
             ast::AssocItemKind::Const(..) => true,
-            ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig),
+            ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
             _ => false,
         };
         self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
index b970c9e4911fafb36ff0612c0e30fb417d46437f..d789237e692d2beea5f514ee6f41b89080674be4 100644 (file)
@@ -68,11 +68,10 @@ pub enum EscapeError {
 impl EscapeError {
     /// Returns true for actual errors, as opposed to warnings.
     pub fn is_fatal(&self) -> bool {
-        match self {
-            EscapeError::UnskippedWhitespaceWarning => false,
-            EscapeError::MultipleSkippedLinesWarning => false,
-            _ => true,
-        }
+        !matches!(
+            self,
+            EscapeError::UnskippedWhitespaceWarning | EscapeError::MultipleSkippedLinesWarning
+        )
     }
 }
 
index c228ecb03fdec25f1d475fd9d9a2ef63ce0c6f0e..f2e4e70a197796923fb8eae72e799cb39d829d74 100644 (file)
@@ -32,8 +32,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
-use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType};
-use rustc_feature::{GateIssue, Stability};
+use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
@@ -369,12 +368,12 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
         match it.kind {
-            ast::ItemKind::Trait(box ast::TraitKind(_, ast::Unsafe::Yes(_), ..)) => self
+            ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
                 .report_unsafe(cx, it.span, |lint| {
                     lint.build("declaration of an `unsafe` trait").emit()
                 }),
 
-            ast::ItemKind::Impl(box ast::ImplKind { unsafety: ast::Unsafe::Yes(_), .. }) => self
+            ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
                 .report_unsafe(cx, it.span, |lint| {
                     lint.build("implementation of an `unsafe` trait").emit()
                 }),
@@ -921,7 +920,7 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
             // This is a hard error in future editions; avoid linting and erroring
             return;
         }
-        if let ast::AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) = it.kind {
+        if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind {
             for arg in sig.decl.inputs.iter() {
                 if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
                     if ident.name == kw::Empty {
@@ -959,7 +958,7 @@ fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
 pub struct DeprecatedAttr {
     // This is not free to compute, so we want to keep it around, rather than
     // compute it for every attribute.
-    depr_attrs: Vec<&'static (Symbol, AttributeType, AttributeTemplate, AttributeGate)>,
+    depr_attrs: Vec<&'static BuiltinAttribute>,
 }
 
 impl_lint_pass!(DeprecatedAttr => []);
@@ -990,14 +989,14 @@ fn lint_deprecated_attr(
 
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
-        for &&(n, _, _, ref g) in &self.depr_attrs {
-            if attr.ident().map(|ident| ident.name) == Some(n) {
+        for BuiltinAttribute { name, gate, .. } in &self.depr_attrs {
+            if attr.ident().map(|ident| ident.name) == Some(*name) {
                 if let &AttributeGate::Gated(
                     Stability::Deprecated(link, suggestion),
                     name,
                     reason,
                     _,
-                ) = g
+                ) = gate
                 {
                     let msg =
                         format!("use of deprecated attribute `{}`: {}. See {}", name, reason, link);
@@ -3130,18 +3129,13 @@ fn is_zero(expr: &hir::Expr<'_>) -> bool {
             false
         }
 
-        if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind {
-            if let rustc_hir::UnOp::Deref = un_op {
-                if is_null_ptr(cx, expr_deref) {
-                    cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
-                        let mut err = lint.build("dereferencing a null pointer");
-                        err.span_label(
-                            expr.span,
-                            "this code causes undefined behavior when executed",
-                        );
-                        err.emit();
-                    });
-                }
+        if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
+            if is_null_ptr(cx, expr_deref) {
+                cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
+                    let mut err = lint.build("dereferencing a null pointer");
+                    err.span_label(expr.span, "this code causes undefined behavior when executed");
+                    err.emit();
+                });
             }
         }
     }
@@ -3196,7 +3190,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
                         let snippet = template_snippet.as_str();
                         if let Some(pos) = snippet.find(needle) {
                             let end = pos
-                                + &snippet[pos..]
+                                + snippet[pos..]
                                     .find(|c| c == ':')
                                     .unwrap_or(snippet[pos..].len() - 1);
                             let inner = InnerSpan::new(pos, end);
index 50a0d211a366a913613ea622df502554413c00bd..c64a67b6b9f1b5c38dbc774948c62c0078930ed7 100644 (file)
@@ -101,33 +101,31 @@ fn check_path(&mut self, cx: &LateContext<'_>, path: &'tcx Path<'tcx>, _: HirId)
 
     fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) {
         match &ty.kind {
-            TyKind::Path(qpath) => {
-                if let QPath::Resolved(_, path) = qpath {
-                    if let Some(last) = path.segments.iter().last() {
-                        if lint_ty_kind_usage(cx, last) {
-                            cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
-                                lint.build("usage of `ty::TyKind`")
-                                    .help("try using `Ty` instead")
-                                    .emit();
-                            })
-                        } else {
-                            if ty.span.from_expansion() {
-                                return;
-                            }
-                            if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
-                                if path.segments.len() > 1 {
-                                    cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
-                                        lint.build(&format!("usage of qualified `ty::{}`", t))
-                                            .span_suggestion(
-                                                path.span,
-                                                "try using it unqualified",
-                                                t,
-                                                // The import probably needs to be changed
-                                                Applicability::MaybeIncorrect,
-                                            )
-                                            .emit();
-                                    })
-                                }
+            TyKind::Path(QPath::Resolved(_, path)) => {
+                if let Some(last) = path.segments.iter().last() {
+                    if lint_ty_kind_usage(cx, last) {
+                        cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
+                            lint.build("usage of `ty::TyKind`")
+                                .help("try using `Ty` instead")
+                                .emit();
+                        })
+                    } else {
+                        if ty.span.from_expansion() {
+                            return;
+                        }
+                        if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
+                            if path.segments.len() > 1 {
+                                cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
+                                    lint.build(&format!("usage of qualified `ty::{}`", t))
+                                        .span_suggestion(
+                                            path.span,
+                                            "try using it unqualified",
+                                            t,
+                                            // The import probably needs to be changed
+                                            Applicability::MaybeIncorrect,
+                                        )
+                                        .emit();
+                                })
                             }
                         }
                     }
@@ -169,37 +167,30 @@ fn lint_ty_kind_usage(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> bool {
 }
 
 fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, ty: &Ty<'_>) -> Option<String> {
-    if let TyKind::Path(qpath) = &ty.kind {
-        if let QPath::Resolved(_, path) = qpath {
-            match path.res {
-                Res::Def(_, def_id) => {
-                    if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id)
-                    {
-                        return Some(format!(
-                            "{}{}",
-                            name,
-                            gen_args(path.segments.last().unwrap())
-                        ));
-                    }
+    if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
+        match path.res {
+            Res::Def(_, def_id) => {
+                if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id) {
+                    return Some(format!("{}{}", name, gen_args(path.segments.last().unwrap())));
                 }
-                // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
-                Res::SelfTy(None, Some((did, _))) => {
-                    if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
-                        if let Some(name @ (sym::Ty | sym::TyCtxt)) =
-                            cx.tcx.get_diagnostic_name(adt.did)
-                        {
-                            // NOTE: This path is currently unreachable as `Ty<'tcx>` is
-                            // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
-                            // is not actually allowed.
-                            //
-                            // I(@lcnr) still kept this branch in so we don't miss this
-                            // if we ever change it in the future.
-                            return Some(format!("{}<{}>", name, substs[0]));
-                        }
+            }
+            // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
+            Res::SelfTy(None, Some((did, _))) => {
+                if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+                    if let Some(name @ (sym::Ty | sym::TyCtxt)) =
+                        cx.tcx.get_diagnostic_name(adt.did)
+                    {
+                        // NOTE: This path is currently unreachable as `Ty<'tcx>` is
+                        // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
+                        // is not actually allowed.
+                        //
+                        // I(@lcnr) still kept this branch in so we don't miss this
+                        // if we ever change it in the future.
+                        return Some(format!("{}<{}>", name, substs[0]));
                     }
                 }
-                _ => (),
             }
+            _ => (),
         }
     }
 
@@ -238,8 +229,7 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
 
 impl EarlyLintPass for LintPassImpl {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
-        if let ast::ItemKind::Impl(box ast::ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind
-        {
+        if let ast::ItemKind::Impl(box ast::Impl { of_trait: Some(lint_pass), .. }) = &item.kind {
             if let Some(last) = lint_pass.path.segments.last() {
                 if last.ident.name == sym::LintPass {
                     let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
index ddbc3c5912836f1f8a9b3525c6045d9715fbca41..4f77db8a24dc4be05217c7cbce4a49b5ca35f44c 100644 (file)
@@ -889,15 +889,17 @@ LLVMRustOptimizeWithNewPassManager(
       OptimizerLastEPCallbacks.push_back(
         [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
           MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
-          MPM.addPass(ModuleAddressSanitizerPass(
-              /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
 #if LLVM_VERSION_GE(14, 0)
-          AddressSanitizerOptions opts(/*CompileKernel=*/false,
-                                       SanitizerOptions->SanitizeAddressRecover,
-                                       /*UseAfterScope=*/true,
-                                       AsanDetectStackUseAfterReturnMode::Runtime);
-          MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts)));
+          AddressSanitizerOptions opts = AddressSanitizerOptions{
+            /*CompileKernel=*/false,
+            SanitizerOptions->SanitizeAddressRecover,
+            /*UseAfterScope=*/true,
+            AsanDetectStackUseAfterReturnMode::Runtime,
+          };
+          MPM.addPass(ModuleAddressSanitizerPass(opts));
 #else
+          MPM.addPass(ModuleAddressSanitizerPass(
+              /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
           MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
               /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
               /*UseAfterScope=*/true)));
index dba885a27fe229f3c73176568cb4891135acf097..63bdcea87f8170a97df6b45df4f8bc8d8032e910 100644 (file)
@@ -24,11 +24,9 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
                         }
                         if meta.path().is_ident("project") {
                             if let Meta::List(list) = meta {
-                                if let Some(nested) = list.nested.iter().next() {
-                                    if let NestedMeta::Meta(meta) = nested {
-                                        attrs.project = meta.path().get_ident().cloned();
-                                        any_attr = true;
-                                    }
+                                if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() {
+                                    attrs.project = meta.path().get_ident().cloned();
+                                    any_attr = true;
                                 }
                             }
                         }
index 95b74fd5306e54c75117f8508669406ca8488873..eb0a693226c480d51c91311cd63ddcc5bd1cfd76 100644 (file)
@@ -29,6 +29,7 @@
 
 use proc_macro::bridge::client::ProcMacro;
 use std::collections::BTreeMap;
+use std::ops::Fn;
 use std::path::Path;
 use std::{cmp, env};
 use tracing::{debug, info};
index 8db2291dfcfaac8c6144128f3e03abd47452e52e..7cba16e0a9ae38d9333afc16d1dc1b0b65699dfc 100644 (file)
@@ -350,6 +350,7 @@ impl<'a> CrateLocator<'a> {
         self.crate_rejections.via_kind.clear();
         self.crate_rejections.via_version.clear();
         self.crate_rejections.via_filename.clear();
+        self.crate_rejections.via_invalid.clear();
     }
 
     crate fn maybe_load_library_crate(&mut self) -> Result<Option<Library>, CrateError> {
@@ -548,7 +549,17 @@ fn extract_one(
                             continue;
                         }
                     }
-                    Err(err) => {
+                    Err(MetadataError::LoadFailure(err)) => {
+                        info!("no metadata found: {}", err);
+                        // The file was present and created by the same compiler version, but we
+                        // couldn't load it for some reason.  Give a hard error instead of silently
+                        // ignoring it, but only if we would have given an error anyway.
+                        self.crate_rejections
+                            .via_invalid
+                            .push(CrateMismatch { path: lib, got: err });
+                        continue;
+                    }
+                    Err(err @ MetadataError::NotPresent(_)) => {
                         info!("no metadata found: {}", err);
                         continue;
                     }
@@ -726,25 +737,28 @@ fn find_commandline_library(&mut self) -> Result<Option<Library>, CrateError> {
 fn get_metadata_section(
     target: &Target,
     flavor: CrateFlavor,
-    filename: &Path,
+    filename: &'p Path,
     loader: &dyn MetadataLoader,
-) -> Result<MetadataBlob, String> {
+) -> Result<MetadataBlob, MetadataError<'p>> {
     if !filename.exists() {
-        return Err(format!("no such file: '{}'", filename.display()));
+        return Err(MetadataError::NotPresent(filename));
     }
     let raw_bytes: MetadataRef = match flavor {
-        CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
+        CrateFlavor::Rlib => {
+            loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
+        }
         CrateFlavor::Dylib => {
-            let buf = loader.get_dylib_metadata(target, filename)?;
+            let buf =
+                loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?;
             // The header is uncompressed
             let header_len = METADATA_HEADER.len();
             debug!("checking {} bytes of metadata-version stamp", header_len);
             let header = &buf[..cmp::min(header_len, buf.len())];
             if header != METADATA_HEADER {
-                return Err(format!(
-                    "incompatible metadata version found: '{}'",
+                return Err(MetadataError::LoadFailure(format!(
+                    "invalid metadata version found: {}",
                     filename.display()
-                ));
+                )));
             }
 
             // Header is okay -> inflate the actual metadata
@@ -756,17 +770,28 @@ fn get_metadata_section(
             match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
                 Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()),
                 Err(_) => {
-                    return Err(format!("failed to decompress metadata: {}", filename.display()));
+                    return Err(MetadataError::LoadFailure(format!(
+                        "failed to decompress metadata: {}",
+                        filename.display()
+                    )));
                 }
             }
         }
         CrateFlavor::Rmeta => {
             // mmap the file, because only a small fraction of it is read.
-            let file = std::fs::File::open(filename)
-                .map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?;
+            let file = std::fs::File::open(filename).map_err(|_| {
+                MetadataError::LoadFailure(format!(
+                    "failed to open rmeta metadata: '{}'",
+                    filename.display()
+                ))
+            })?;
             let mmap = unsafe { Mmap::map(file) };
-            let mmap = mmap
-                .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?;
+            let mmap = mmap.map_err(|_| {
+                MetadataError::LoadFailure(format!(
+                    "failed to mmap rmeta metadata: '{}'",
+                    filename.display()
+                ))
+            })?;
 
             rustc_erase_owner!(OwningRef::new(mmap).map_owner_box())
         }
@@ -775,7 +800,10 @@ fn get_metadata_section(
     if blob.is_compatible() {
         Ok(blob)
     } else {
-        Err(format!("incompatible metadata version found: '{}'", filename.display()))
+        Err(MetadataError::LoadFailure(format!(
+            "invalid metadata version found: {}",
+            filename.display()
+        )))
     }
 }
 
@@ -854,6 +882,7 @@ struct CrateRejections {
     via_kind: Vec<CrateMismatch>,
     via_version: Vec<CrateMismatch>,
     via_filename: Vec<CrateMismatch>,
+    via_invalid: Vec<CrateMismatch>,
 }
 
 /// Candidate rejection reasons collected during crate search.
@@ -883,6 +912,24 @@ struct CrateRejections {
     NonDylibPlugin(Symbol),
 }
 
+enum MetadataError<'a> {
+    /// The file was missing.
+    NotPresent(&'a Path),
+    /// The file was present and invalid.
+    LoadFailure(String),
+}
+
+impl fmt::Display for MetadataError<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            MetadataError::NotPresent(filename) => {
+                f.write_str(&format!("no such file: '{}'", filename.display()))
+            }
+            MetadataError::LoadFailure(msg) => f.write_str(msg),
+        }
+    }
+}
+
 impl CrateError {
     crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! {
         let mut err = match self {
@@ -1064,6 +1111,19 @@ impl CrateError {
                     }
                     err.note(&msg);
                     err
+                } else if !locator.crate_rejections.via_invalid.is_empty() {
+                    let mut err = struct_span_err!(
+                        sess,
+                        span,
+                        E0786,
+                        "found invalid metadata files for crate `{}`{}",
+                        crate_name,
+                        add,
+                    );
+                    for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
+                        err.note(&got);
+                    }
+                    err
                 } else {
                     let mut err = struct_span_err!(
                         sess,
index 2431b819a3f30e25d3507cd84c735703a2205771..bd5cda15b91abcfc18b6a6cc8ac089d25e7c5389 100644 (file)
@@ -309,7 +309,7 @@ fn process_command_line(&mut self) {
                     .libs
                     .iter()
                     .filter_map(|lib| lib.name.as_ref())
-                    .any(|n| &n.as_str() == &lib.name);
+                    .any(|n| n.as_str() == lib.name);
                 if new_name.is_empty() {
                     self.tcx.sess.err(&format!(
                         "an empty renaming target was specified for library `{}`",
index 5e90aec003e9b1a20e381b1069059a87b1125bc6..b2c7818a542189e79382e475f39f44d4b67e4c72 100644 (file)
@@ -1179,7 +1179,7 @@ fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), ses
                             let ctor_res =
                                 Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
                             let mut vis = self.get_visibility(ctor_def_id.index);
-                            if ctor_def_id == def_id && vis == ty::Visibility::Public {
+                            if ctor_def_id == def_id && vis.is_public() {
                                 // For non-exhaustive variants lower the constructor visibility to
                                 // within the crate. We only need this for fictive constructors,
                                 // for other constructors correct visibilities
index 7ea004b16f23bc3546f4db41827ca4ef927a22a0..eeb0a77adc0ad73b06de2d381df0f1e0f2e01ac8 100644 (file)
@@ -318,7 +318,7 @@ pub fn provide(providers: &mut Providers) {
             }
 
             let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
-                if child.vis != ty::Visibility::Public {
+                if !child.vis.is_public() {
                     return;
                 }
 
index 0dbef66ac37d77ff78eeb6fa2fb10a5986f1e1f3..d46829c2ceea693b047305ca5165b8dd0696a9fd 100644 (file)
@@ -797,6 +797,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::ConstParam
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -832,6 +833,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         DefKind::Use
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -856,9 +858,11 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
             (true, mir_opt_base)
         }
         // Constants
-        DefKind::AnonConst | DefKind::AssocConst | DefKind::Static | DefKind::Const => {
-            (true, false)
-        }
+        DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::AssocConst
+        | DefKind::Static
+        | DefKind::Const => (true, false),
         // Full-fledged functions
         DefKind::AssocFn | DefKind::Fn => {
             let generics = tcx.generics_of(def_id);
@@ -914,6 +918,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::Use
         | DefKind::LifetimeParam
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::Generator
@@ -939,6 +944,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::AssocFn
         | DefKind::AssocConst
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::Impl
         | DefKind::Field
@@ -2187,5 +2193,8 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
     result[header + 2] = (pos >> 8) as u8;
     result[header + 3] = (pos >> 0) as u8;
 
+    // Record metadata size for self-profiling
+    tcx.prof.artifact_size("crate_metadata", "crate_metadata", result.len() as u64);
+
     EncodedMetadata { raw_data: result }
 }
index 8f52e16c2ebe41e7873d6893dc0917be4e1a37a4..d9d0781b37aacefe4afab97366de2b6448907d6e 100644 (file)
@@ -266,7 +266,15 @@ pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
                 };
                 DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
             }
-            Node::AnonConst(_) => DefKind::AnonConst,
+            Node::AnonConst(_) => {
+                let inline = match self.find(self.get_parent_node(hir_id)) {
+                    Some(Node::Expr(&Expr {
+                        kind: ExprKind::ConstBlock(ref anon_const), ..
+                    })) if anon_const.hir_id == hir_id => true,
+                    _ => false,
+                };
+                if inline { DefKind::InlineConst } else { DefKind::AnonConst }
+            }
             Node::Field(_) => DefKind::Field,
             Node::Expr(expr) => match expr.kind {
                 ExprKind::Closure(.., None) => DefKind::Closure,
index 1eba2994ed36e89af4038a3193094648d59e5500..0e70d49ef49d25faa9f12189bb36f4b394d4b220 100644 (file)
@@ -248,8 +248,12 @@ fn struct_lint_level_impl(
             (Level::Warn, None) => sess.struct_warn(""),
             (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""),
             (Level::ForceWarn, None) => sess.struct_force_warn(""),
-            (Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
-            (Level::Deny | Level::Forbid, None) => sess.struct_err(""),
+            (Level::Deny | Level::Forbid, Some(span)) => {
+                let mut builder = sess.diagnostic().struct_err_lint("");
+                builder.set_span(span);
+                builder
+            }
+            (Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
         };
 
         // If this code originates in a foreign macro, aka something that this crate
index 9472a287e5a41907c5f434729376484048582a1e..7a51bb4a1f32ae828f9de259450a815ba37981c1 100644 (file)
@@ -538,12 +538,12 @@ impl InterpError<'_> {
     /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
     /// so this method lets us detect them and `bug!` on unexpected errors.
     pub fn formatted_string(&self) -> bool {
-        match self {
+        matches!(
+            self,
             InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
-            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
-            | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true,
-            _ => false,
-        }
+                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
+                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
+        )
     }
 
     /// Should this error be reported as a hard error, preventing compilation, or a soft error,
index 971556d4463004328c08c94838ebf1b73b3528e5..253ac266bedaa246cc1039b9a6e5191447cb152b 100644 (file)
@@ -2665,7 +2665,7 @@ fn map_projections(
         mut self,
         mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
     ) -> Self {
-        self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
+        self.contents = self.contents.into_iter().map(|(proj, span)| (f(proj), span)).collect();
         self
     }
 
index 8e363cfbff562d594d9850dfa52c0a6ed2ed553e..8e1b887f87da75695eb5c41a6156250db02171e8 100644 (file)
@@ -958,7 +958,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res
             write!(w, "static {}", if tcx.is_mutable_static(def_id) { "mut " } else { "" })?
         }
         (_, _) if is_function => write!(w, "fn ")?,
-        (DefKind::AnonConst, _) => {} // things like anon const, not an item
+        (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item
         _ => bug!("Unexpected def kind {:?}", kind),
     }
 
index 06041bbb02d355537240c012aefb6835520036d4..9a58009a173d4df85b4d837bd16b06389170fead 100644 (file)
     /// additional requirements that the closure's creator must verify.
     query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
-        cache_on_disk_if(tcx) { tcx.is_closure(key.to_def_id()) }
+        cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
     }
     query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc {
         desc { "check for overlap between inherent impls defined in this crate" }
     }
 
+    /// Checks whether all impls in the crate pass the overlap check, returning
+    /// which impls fail it. If all impls are correct, the returned slice is empty.
+    query orphan_check_crate(_: ()) -> &'tcx [LocalDefId] {
+        desc {
+            "checking whether the immpl in the this crate follow the orphan rules",
+        }
+    }
+
     /// Check whether the function has any recursion that could cause the inliner to trigger
     /// a cycle. Returns the call stack causing the cycle. The call stack does not contain the
     /// current function, just all intermediate functions.
     }
 
     /// Return all `impl` blocks in the current crate.
-    ///
-    /// To allow caching this between crates, you must pass in [`LOCAL_CRATE`] as the crate number.
-    /// Passing in any other crate will cause an ICE.
-    ///
-    /// [`LOCAL_CRATE`]: rustc_hir::def_id::LOCAL_CRATE
     query all_local_trait_impls(_: ()) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> {
         desc { "local trait impls" }
     }
index 6570d8e15679da6143c74ec0324fe8095f885e6e..245df6361076f93a5c5eceeab0661828f39d129c 100644 (file)
@@ -267,14 +267,12 @@ pub enum ObligationCauseCode<'tcx> {
 
     /// Error derived when matching traits/impls; see ObligationCause for more details
     CompareImplMethodObligation {
-        item_name: Symbol,
         impl_item_def_id: DefId,
         trait_item_def_id: DefId,
     },
 
     /// Error derived when matching traits/impls; see ObligationCause for more details
     CompareImplTypeObligation {
-        item_name: Symbol,
         impl_item_def_id: DefId,
         trait_item_def_id: DefId,
     },
index 869b2ab9dbcbc5a02495d8b515f6963ad1f10e6c..27e22ccac02a7fb7c771700ada2318eeace3a841 100644 (file)
@@ -1,7 +1,9 @@
 use crate::mir::interpret::ConstValue;
 use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{ParamEnv, ParamEnvAnd};
+use crate::ty::{
+    self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
+    TyCtxt, TypeFoldable,
+};
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -54,6 +56,24 @@ pub fn from_opt_const_arg_anon_const(
 
         let ty = tcx.type_of(def.def_id_for_type_of());
 
+        match Self::try_eval_lit_or_param(tcx, ty, expr) {
+            Some(v) => v,
+            None => tcx.mk_const(ty::Const {
+                val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                    def: def.to_global(),
+                    substs_: None,
+                    promoted: None,
+                }),
+                ty,
+            }),
+        }
+    }
+
+    fn try_eval_lit_or_param(
+        tcx: TyCtxt<'tcx>,
+        ty: Ty<'tcx>,
+        expr: &'tcx hir::Expr<'tcx>,
+    ) -> Option<&'tcx Self> {
         let lit_input = match expr.kind {
             hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
             hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
@@ -69,7 +89,7 @@ pub fn from_opt_const_arg_anon_const(
             // If an error occurred, ignore that it's a literal and leave reporting the error up to
             // mir.
             if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
-                return c;
+                return Some(c);
             } else {
                 tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const");
             }
@@ -85,7 +105,7 @@ pub fn from_opt_const_arg_anon_const(
         };
 
         use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
-        let val = match expr.kind {
+        match expr.kind {
             ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
                 // Find the name and index of the const parameter by indexing the generics of
                 // the parent item and construct a `ParamConst`.
@@ -95,16 +115,53 @@ pub fn from_opt_const_arg_anon_const(
                 let generics = tcx.generics_of(item_def_id.to_def_id());
                 let index = generics.param_def_id_to_index[&def_id];
                 let name = tcx.hir().name(hir_id);
-                ty::ConstKind::Param(ty::ParamConst::new(index, name))
+                Some(tcx.mk_const(ty::Const {
+                    val: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
+                    ty,
+                }))
             }
-            _ => ty::ConstKind::Unevaluated(ty::Unevaluated {
-                def: def.to_global(),
-                substs_: None,
-                promoted: None,
-            }),
+            _ => None,
+        }
+    }
+
+    pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self {
+        debug!("Const::from_inline_const(def_id={:?})", def_id);
+
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+
+        let body_id = match tcx.hir().get(hir_id) {
+            hir::Node::AnonConst(ac) => ac.body,
+            _ => span_bug!(
+                tcx.def_span(def_id.to_def_id()),
+                "from_inline_const can only process anonymous constants"
+            ),
         };
 
-        tcx.mk_const(ty::Const { val, ty })
+        let expr = &tcx.hir().body(body_id).value;
+
+        let ty = tcx.typeck(def_id).node_type(hir_id);
+
+        let ret = match Self::try_eval_lit_or_param(tcx, ty, expr) {
+            Some(v) => v,
+            None => {
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
+                let parent_substs =
+                    tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
+                let substs =
+                    InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
+                        .substs;
+                tcx.mk_const(ty::Const {
+                    val: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                        def: ty::WithOptConstParam::unknown(def_id).to_global(),
+                        substs_: Some(substs),
+                        promoted: None,
+                    }),
+                    ty,
+                })
+            }
+        };
+        debug_assert!(!ret.has_free_regions(tcx));
+        ret
     }
 
     /// Interns the given value as a constant.
index 2bd9415171d7d5d2ac0af852205e531aa736a01c..b14a69892657bcb7bce9c32efc9c9314f5df4b73 100644 (file)
@@ -42,6 +42,7 @@ pub enum TypeError<'tcx> {
     TupleSize(ExpectedFound<usize>),
     FixedArraySize(ExpectedFound<u64>),
     ArgCount,
+    FieldMisMatch(Symbol, Symbol),
 
     RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
     RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
@@ -134,6 +135,7 @@ fn report_maybe_different(
                 pluralize!(values.found)
             ),
             ArgCount => write!(f, "incorrect number of function parameters"),
+            FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
             RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
             RegionsInsufficientlyPolymorphic(br, _) => write!(
                 f,
@@ -224,6 +226,7 @@ pub fn must_include_note(&self) -> bool {
             | ArgumentMutability(_)
             | TupleSize(_)
             | ArgCount
+            | FieldMisMatch(..)
             | RegionsDoesNotOutlive(..)
             | RegionsInsufficientlyPolymorphic(..)
             | RegionsOverlyPolymorphic(..)
index cf47da157d19f7c969eb8e0e9724d06056f052f0..673733faa766ff5846c02075833be4fba79c0cf7 100644 (file)
     Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind,
     CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion,
     ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
-    GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
-    PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
-    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
+    GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst,
+    ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig,
+    PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut,
+    UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
 };
 pub use self::trait_def::TraitDef;
 
@@ -332,6 +333,10 @@ pub fn is_visible_locally(self) -> bool {
             Visibility::Invisible => false,
         }
     }
+
+    pub fn is_public(self) -> bool {
+        matches!(self, Visibility::Public)
+    }
 }
 
 /// The crate variances map is computed during typeck and contains the
@@ -1927,7 +1932,8 @@ pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
                 | DefKind::Static
                 | DefKind::AssocConst
                 | DefKind::Ctor(..)
-                | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def),
+                | DefKind::AnonConst
+                | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
                 // If the caller wants `mir_for_ctfe` of a function they should not be using
                 // `instance_mir`, so we'll assume const fn also wants the optimized version.
                 _ => {
index 742005e245f9d160ed91387e209975e1f1ddf0da..5d9e7aaf72f8eece66bbee1f08eaab6b1f74aa70 100644 (file)
@@ -2404,7 +2404,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
     // Iterate external crate defs but be mindful about visibility
     while let Some(def) = queue.pop() {
         for child in tcx.item_children(def).iter() {
-            if child.vis != ty::Visibility::Public {
+            if !child.vis.is_public() {
                 continue;
             }
 
index 8b20e1eec9a86e03ba2d3992530b195e385f4a59..c7d8bec506f6b80af01ed5e80d120ea8879ac7bb 100644 (file)
@@ -187,8 +187,12 @@ fn relate<R: TypeRelation<'tcx>>(
             })
             .enumerate()
             .map(|(i, r)| match r {
-                Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)),
-                Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)),
+                Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
+                    Err(TypeError::ArgumentSorts(exp_found, i))
+                }
+                Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
+                    Err(TypeError::ArgumentMutability(i))
+                }
                 r => r,
             });
         Ok(ty::FnSig {
index d6069395474ab21ddd877c02e804944deafc7d44..0f8e80806e31e430edc9dc4ff13fc80fb94b4489 100644 (file)
@@ -602,6 +602,7 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
             TupleSize(x) => TupleSize(x),
             FixedArraySize(x) => FixedArraySize(x),
             ArgCount => ArgCount,
+            FieldMisMatch(x, y) => FieldMisMatch(x, y),
             RegionsDoesNotOutlive(a, b) => {
                 return tcx.lift((a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b));
             }
index 874de3366d79213ee7499075d518f5a41f3eb58d..e57075ed33811d59589d3f340ef2f5c0ae272a1a 100644 (file)
@@ -704,6 +704,66 @@ pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
     }
 }
 
+/// An inline const is modeled like
+///
+///     const InlineConst<'l0...'li, T0...Tj, R>: R;
+///
+/// where:
+///
+/// - 'l0...'li and T0...Tj are the generic parameters
+///   inherited from the item that defined the inline const,
+/// - R represents the type of the constant.
+///
+/// When the inline const is instantiated, `R` is substituted as the actual inferred
+/// type of the constant. The reason that `R` is represented as an extra type parameter
+/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
+/// inline const can reference lifetimes that are internal to the creating function.
+#[derive(Copy, Clone, Debug, TypeFoldable)]
+pub struct InlineConstSubsts<'tcx> {
+    /// Generic parameters from the enclosing item,
+    /// concatenated with the inferred type of the constant.
+    pub substs: SubstsRef<'tcx>,
+}
+
+/// Struct returned by `split()`.
+pub struct InlineConstSubstsParts<'tcx, T> {
+    pub parent_substs: &'tcx [GenericArg<'tcx>],
+    pub ty: T,
+}
+
+impl<'tcx> InlineConstSubsts<'tcx> {
+    /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`.
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>,
+    ) -> InlineConstSubsts<'tcx> {
+        InlineConstSubsts {
+            substs: tcx.mk_substs(
+                parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())),
+            ),
+        }
+    }
+
+    /// Divides the inline const substs into their respective components.
+    /// The ordering assumed here must match that used by `InlineConstSubsts::new` above.
+    fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> {
+        match self.substs[..] {
+            [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty },
+            _ => bug!("inline const substs missing synthetics"),
+        }
+    }
+
+    /// Returns the substitutions of the inline const's parent.
+    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent_substs
+    }
+
+    /// Returns the type of this inline const.
+    pub fn ty(self) -> Ty<'tcx> {
+        self.split().ty.expect_ty()
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub enum ExistentialPredicate<'tcx> {
index 2438d1a16021b50aa4f318d5946842e6bc6d4281..73a8e18949de06ad6a4d8d5b3dc0c8329b5c22bf 100644 (file)
@@ -3,7 +3,7 @@
 use crate::mir;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
+use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
 use rustc_hir::def_id::DefId;
@@ -204,6 +204,14 @@ pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> {
         GeneratorSubsts { substs: self }
     }
 
+    /// Interpret these substitutions as the substitutions of an inline const.
+    /// Inline const substitutions have a particular structure controlled by the
+    /// compiler that encodes information like the inferred type;
+    /// see `ty::InlineConstSubsts` struct for more comments.
+    pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> {
+        InlineConstSubsts { substs: self }
+    }
+
     /// Creates an `InternalSubsts` that maps each generic parameter to itself.
     pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
         Self::for_item(tcx, def_id, |param, _| tcx.mk_param_from_def(param))
index 2c884813d23187eea6f275f54c9cffb979085a36..6b287445ff032dade94803d5ba345326d7d7ac98 100644 (file)
@@ -423,6 +423,15 @@ pub fn is_closure(self, def_id: DefId) -> bool {
         matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Generator)
     }
 
+    /// Returns `true` if `def_id` refers to a definition that does not have its own
+    /// type-checking context, i.e. closure, generator or inline const.
+    pub fn is_typeck_child(self, def_id: DefId) -> bool {
+        matches!(
+            self.def_kind(def_id),
+            DefKind::Closure | DefKind::Generator | DefKind::InlineConst
+        )
+    }
+
     /// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
     pub fn is_trait(self, def_id: DefId) -> bool {
         self.def_kind(def_id) == DefKind::Trait
@@ -440,16 +449,19 @@ pub fn is_constructor(self, def_id: DefId) -> bool {
         matches!(self.def_kind(def_id), DefKind::Ctor(..))
     }
 
-    /// Given the def-ID of a fn or closure, returns the def-ID of
-    /// the innermost fn item that the closure is contained within.
-    /// This is a significant `DefId` because, when we do
-    /// type-checking, we type-check this fn item and all of its
-    /// (transitive) closures together. Therefore, when we fetch the
+    /// Given the `DefId`, returns the `DefId` of the innermost item that
+    /// has its own type-checking context or "inference enviornment".
+    ///
+    /// For example, a closure has its own `DefId`, but it is type-checked
+    /// with the containing item. Similarly, an inline const block has its
+    /// own `DefId` but it is type-checked together with the containing item.
+    ///
+    /// Therefore, when we fetch the
     /// `typeck` the closure, for example, we really wind up
     /// fetching the `typeck` the enclosing fn item.
-    pub fn closure_base_def_id(self, def_id: DefId) -> DefId {
+    pub fn typeck_root_def_id(self, def_id: DefId) -> DefId {
         let mut def_id = def_id;
-        while self.is_closure(def_id) {
+        while self.is_typeck_child(def_id) {
             def_id = self.parent(def_id).unwrap_or_else(|| {
                 bug!("closure {:?} has no parent", def_id);
             });
index da857b0a403b4f909e8d0d9a332a7c5714577516..08977049db02d772e5ab0e1e5b0ec90782af9a14 100644 (file)
@@ -34,7 +34,7 @@ pub fn record_time<T, F>(accu: &Lock<Duration>, f: F) -> T
     let rv = f();
     let duration = start.elapsed();
     let mut accu = accu.lock();
-    *accu = *accu + duration;
+    *accu += duration;
     rv
 }
 
index 17296a95bc17e26e2c6560ea91001e977c8841e7..b4005ccd1cc42205db0909d37699f2b802fbf561 100644 (file)
@@ -578,7 +578,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
 
             hir::ExprKind::ConstBlock(ref anon_const) => {
                 let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+                let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
 
                 ExprKind::ConstBlock { value }
             }
index cb74ae4df2ef86ac4084583730a0d4343f20307e..ce80214c875fc5e46f329f65fc438f031759bed7 100644 (file)
@@ -544,7 +544,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
             let (lit, neg) = match expr.kind {
                 hir::ExprKind::ConstBlock(ref anon_const) => {
                     let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
-                    let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+                    let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id);
                     if matches!(value.val, ConstKind::Param(_)) {
                         let span = self.tcx.hir().span(anon_const.hir_id);
                         self.errors.push(PatternError::ConstParamInPattern(span));
index d959d2f7f6f3f9ca292c8cd072b0799bf5c06486..3ed434131b292ca5920cfea7a223be4704ec66cb 100644 (file)
@@ -443,9 +443,7 @@ pub(super) fn column_count(&self) -> Option<usize> {
     /// expands it.
     fn push(&mut self, row: PatStack<'p, 'tcx>) {
         if !row.is_empty() && row.head().is_or_pat() {
-            for row in row.expand_or_pat() {
-                self.patterns.push(row);
-            }
+            self.patterns.extend(row.expand_or_pat());
         } else {
             self.patterns.push(row);
         }
@@ -797,7 +795,7 @@ fn is_useful<'p, 'tcx>(
         return ret;
     }
 
-    assert!(rows.iter().all(|r| r.len() == v.len()));
+    debug_assert!(rows.iter().all(|r| r.len() == v.len()));
 
     let ty = v.head().ty();
     let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
index 4ac93f716192308709d3c18b73b58d8cb63041f6..6807d02519e2b3305f46278f1b33f861fafb14bd 100644 (file)
@@ -485,7 +485,7 @@ fn inject_statement(
 
 // Non-code expressions are injected into the coverage map, without generating executable code.
 fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) {
-    debug_assert!(if let CoverageKind::Expression { .. } = expression { true } else { false });
+    debug_assert!(matches!(expression, CoverageKind::Expression { .. }));
     debug!("  injecting non-code expression {:?}", expression);
     let inject_in_bb = mir::START_BLOCK;
     let data = &mut mir_body[inject_in_bb];
index cc525a4d6b91ca1a1ab9e491b4086c57a6c46885..d13fa0729cd9562a0306ef1be170dd3a302fb3a4 100644 (file)
@@ -94,10 +94,9 @@ pub fn for_statement(
         stmt_index: usize,
     ) -> Self {
         let is_closure = match statement.kind {
-            StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => match kind {
-                AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _) => true,
-                _ => false,
-            },
+            StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => {
+                matches!(kind, AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _))
+            }
             _ => false,
         };
 
index 7b4eb4912cb366a99319ceb5a309131cad6db06f..6c423a2bb5756c79476adf6a8186781b61c29914 100644 (file)
@@ -11,7 +11,7 @@ impl<'tcx> MirPass<'tcx> for RevealAll {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // This pass must run before inlining, since we insert callee bodies in RevealAll mode.
         // Do not apply this transformation to generators.
-        if (tcx.sess.mir_opt_level() >= 3 || !super::inline::is_enabled(tcx))
+        if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx))
             && body.generator.is_none()
         {
             let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
index f2ea5fedc625c68596af7464c4e7dc9598a1cfda..f59aaa664f3ad02f1d150a09ee65087462e02373 100644 (file)
@@ -310,7 +310,6 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
 
     match self_ty.kind() {
         _ if is_copy => builder.copy_shim(),
-        ty::Array(ty, len) => builder.array_shim(dest, src, ty, len),
         ty::Closure(_, substs) => {
             builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys())
         }
@@ -459,154 +458,6 @@ fn make_clone_call(
         );
     }
 
-    fn loop_header(
-        &mut self,
-        beg: Place<'tcx>,
-        end: Place<'tcx>,
-        loop_body: BasicBlock,
-        loop_end: BasicBlock,
-        is_cleanup: bool,
-    ) {
-        let tcx = self.tcx;
-
-        let cond = self.make_place(Mutability::Mut, tcx.types.bool);
-        let compute_cond = self.make_statement(StatementKind::Assign(Box::new((
-            cond,
-            Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Copy(end), Operand::Copy(beg)))),
-        ))));
-
-        // `if end != beg { goto loop_body; } else { goto loop_end; }`
-        self.block(
-            vec![compute_cond],
-            TerminatorKind::if_(tcx, Operand::Move(cond), loop_body, loop_end),
-            is_cleanup,
-        );
-    }
-
-    fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
-        Box::new(Constant {
-            span: self.span,
-            user_ty: None,
-            literal: ty::Const::from_usize(self.tcx, value).into(),
-        })
-    }
-
-    fn array_shim(
-        &mut self,
-        dest: Place<'tcx>,
-        src: Place<'tcx>,
-        ty: Ty<'tcx>,
-        len: &'tcx ty::Const<'tcx>,
-    ) {
-        let tcx = self.tcx;
-        let span = self.span;
-
-        let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span));
-        let end = self.make_place(Mutability::Not, tcx.types.usize);
-
-        // BB #0
-        // `let mut beg = 0;`
-        // `let end = len;`
-        // `goto #1;`
-        let inits = vec![
-            self.make_statement(StatementKind::Assign(Box::new((
-                Place::from(beg),
-                Rvalue::Use(Operand::Constant(self.make_usize(0))),
-            )))),
-            self.make_statement(StatementKind::Assign(Box::new((
-                end,
-                Rvalue::Use(Operand::Constant(Box::new(Constant {
-                    span: self.span,
-                    user_ty: None,
-                    literal: len.into(),
-                }))),
-            )))),
-        ];
-        self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false);
-
-        // BB #1: loop {
-        //     BB #2;
-        //     BB #3;
-        // }
-        // BB #4;
-        self.loop_header(Place::from(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
-
-        // BB #2
-        // `dest[i] = Clone::clone(src[beg])`;
-        // Goto #3 if ok, #5 if unwinding happens.
-        let dest_field = self.tcx.mk_place_index(dest, beg);
-        let src_field = self.tcx.mk_place_index(src, beg);
-        self.make_clone_call(dest_field, src_field, ty, BasicBlock::new(3), BasicBlock::new(5));
-
-        // BB #3
-        // `beg = beg + 1;`
-        // `goto #1`;
-        let statements = vec![self.make_statement(StatementKind::Assign(Box::new((
-            Place::from(beg),
-            Rvalue::BinaryOp(
-                BinOp::Add,
-                Box::new((Operand::Copy(Place::from(beg)), Operand::Constant(self.make_usize(1)))),
-            ),
-        ))))];
-        self.block(statements, TerminatorKind::Goto { target: BasicBlock::new(1) }, false);
-
-        // BB #4
-        // `return dest;`
-        self.block(vec![], TerminatorKind::Return, false);
-
-        // BB #5 (cleanup)
-        // `let end = beg;`
-        // `let mut beg = 0;`
-        // goto #6;
-        let end = beg;
-        let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span));
-        let init = self.make_statement(StatementKind::Assign(Box::new((
-            Place::from(beg),
-            Rvalue::Use(Operand::Constant(self.make_usize(0))),
-        ))));
-        self.block(vec![init], TerminatorKind::Goto { target: BasicBlock::new(6) }, true);
-
-        // BB #6 (cleanup): loop {
-        //     BB #7;
-        //     BB #8;
-        // }
-        // BB #9;
-        self.loop_header(
-            Place::from(beg),
-            Place::from(end),
-            BasicBlock::new(7),
-            BasicBlock::new(9),
-            true,
-        );
-
-        // BB #7 (cleanup)
-        // `drop(dest[beg])`;
-        self.block(
-            vec![],
-            TerminatorKind::Drop {
-                place: self.tcx.mk_place_index(dest, beg),
-                target: BasicBlock::new(8),
-                unwind: None,
-            },
-            true,
-        );
-
-        // BB #8 (cleanup)
-        // `beg = beg + 1;`
-        // `goto #6;`
-        let statement = self.make_statement(StatementKind::Assign(Box::new((
-            Place::from(beg),
-            Rvalue::BinaryOp(
-                BinOp::Add,
-                Box::new((Operand::Copy(Place::from(beg)), Operand::Constant(self.make_usize(1)))),
-            ),
-        ))));
-        self.block(vec![statement], TerminatorKind::Goto { target: BasicBlock::new(6) }, true);
-
-        // BB #9 (resume)
-        self.block(vec![], TerminatorKind::Resume, true);
-    }
-
     fn tuple_like_shim<I>(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I)
     where
         I: Iterator<Item = Ty<'tcx>>,
index baf381081ddab019de0e25c8ef10278fbf82f2cc..64cd6f56a9ffa0a15d254c302587bb0f4e9cccc6 100644 (file)
@@ -27,9 +27,8 @@ fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // This is a temporary solution that handles possibly diverging asm statements.
             // Accompanying testcases: mir-opt/unreachable_asm.rs and mir-opt/unreachable_asm_2.rs
             let asm_stmt_in_block = || {
-                bb_data.statements.iter().any(|stmt: &Statement<'_>| match stmt.kind {
-                    StatementKind::LlvmInlineAsm(..) => true,
-                    _ => false,
+                bb_data.statements.iter().any(|stmt: &Statement<'_>| {
+                    matches!(stmt.kind, StatementKind::LlvmInlineAsm(..))
                 })
             };
 
index 7a7a56a034ed28e1e97379fbce53b46fd7db60aa..658c9028ca1a1d0e3866bf9b74875d74a959ae4a 100644 (file)
@@ -361,6 +361,17 @@ fn collect_and_partition_mono_items<'tcx>(
         )
     });
 
+    if tcx.prof.enabled() {
+        // Record CGU size estimates for self-profiling.
+        for cgu in codegen_units {
+            tcx.prof.artifact_size(
+                "codegen_unit_size_estimate",
+                &cgu.name().as_str()[..],
+                cgu.size_estimate() as u64,
+            );
+        }
+    }
+
     let mono_items: DefIdSet = items
         .iter()
         .filter_map(|mono_item| match *mono_item {
index e6e4438b6d41afa63bb448bbc1db8b81cfd51e17..595080619da6faaac8be4cf5b91b93beb4cbf45a 100644 (file)
@@ -167,6 +167,7 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::Use
         | DefKind::ForeignMod
         | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::Field
         | DefKind::LifetimeParam
@@ -195,7 +196,7 @@ fn emit_unused_generic_params_error<'tcx>(
     generics: &'tcx ty::Generics,
     unused_parameters: &FiniteBitSet<u32>,
 ) {
-    let base_def_id = tcx.closure_base_def_id(def_id);
+    let base_def_id = tcx.typeck_root_def_id(def_id);
     if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) {
         return;
     }
@@ -303,7 +304,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                 ControlFlow::CONTINUE
             }
             ty::ConstKind::Unevaluated(uv)
-                if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst =>
+                if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) =>
             {
                 self.visit_child_body(uv.def.did, uv.substs(self.tcx));
                 ControlFlow::CONTINUE
index d2167c7a5db0c8f642f61c047f5b3b54b39372eb..73ca809ab1d3a53f72523025251250e2bd842f18 100644 (file)
@@ -220,7 +220,7 @@ fn parse_item_kind(
         } else if self.check_fn_front_matter(def_final) {
             // FUNCTION ITEM
             let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
-            (ident, ItemKind::Fn(Box::new(FnKind(def(), sig, generics, body))))
+            (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body })))
         } else if self.eat_keyword(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
                 // EXTERN CRATE
@@ -560,7 +560,7 @@ fn parse_item_impl(
                 };
                 let trait_ref = TraitRef { path, ref_id: ty_first.id };
 
-                ItemKind::Impl(Box::new(ImplKind {
+                ItemKind::Impl(Box::new(Impl {
                     unsafety,
                     polarity,
                     defaultness,
@@ -573,7 +573,7 @@ fn parse_item_impl(
             }
             None => {
                 // impl Type
-                ItemKind::Impl(Box::new(ImplKind {
+                ItemKind::Impl(Box::new(Impl {
                     unsafety,
                     polarity,
                     defaultness,
@@ -682,7 +682,7 @@ fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<
 
         self.expect_keyword(kw::Trait)?;
         let ident = self.parse_ident()?;
-        let mut tps = self.parse_generics()?;
+        let mut generics = self.parse_generics()?;
 
         // Parse optional colon and supertrait bounds.
         let had_colon = self.eat(&token::Colon);
@@ -702,7 +702,7 @@ fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<
             }
 
             let bounds = self.parse_generic_bounds(None)?;
-            tps.where_clause = self.parse_where_clause()?;
+            generics.where_clause = self.parse_where_clause()?;
             self.expect_semi()?;
 
             let whole_span = lo.to(self.prev_token.span);
@@ -717,12 +717,15 @@ fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<
 
             self.sess.gated_spans.gate(sym::trait_alias, whole_span);
 
-            Ok((ident, ItemKind::TraitAlias(tps, bounds)))
+            Ok((ident, ItemKind::TraitAlias(generics, bounds)))
         } else {
             // It's a normal trait.
-            tps.where_clause = self.parse_where_clause()?;
+            generics.where_clause = self.parse_where_clause()?;
             let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
-            Ok((ident, ItemKind::Trait(Box::new(TraitKind(is_auto, unsafety, tps, bounds, items)))))
+            Ok((
+                ident,
+                ItemKind::Trait(Box::new(Trait { is_auto, unsafety, generics, bounds, items })),
+            ))
         }
     }
 
@@ -769,7 +772,7 @@ fn parse_assoc_item(
     /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
     /// ```
     /// The `"type"` has already been eaten.
-    fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> {
+    fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -778,10 +781,10 @@ fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> {
             if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
         generics.where_clause = self.parse_where_clause()?;
 
-        let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
+        let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
         self.expect_semi()?;
 
-        Ok((ident, ItemKind::TyAlias(Box::new(TyAliasKind(def, generics, bounds, default)))))
+        Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
     }
 
     /// Parses a `UseTree`.
@@ -1039,9 +1042,7 @@ fn recover_const_impl(
         };
 
         match impl_info.1 {
-            ItemKind::Impl(box ImplKind {
-                of_trait: Some(ref trai), ref mut constness, ..
-            }) => {
+            ItemKind::Impl(box Impl { of_trait: Some(ref trai), ref mut constness, .. }) => {
                 *constness = Const::Yes(const_span);
 
                 let before_trait = trai.path.span.shrink_to_lo();
index 2aa20d02c8830cd38437848b9de82b00040e1bf5..4781813ee8e5641ee25deb2122cc1524b5de528b 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_ast::tokenstream::{DelimSpan, TokenTree};
 use rustc_ast::{self as ast, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
 use rustc_errors::{Applicability, FatalError, PResult};
-use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
+use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Symbol};
@@ -15,14 +15,13 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
         return;
     }
 
-    let attr_info =
-        attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a);
+    let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
 
     // Check input tokens for built-in and key-value attributes.
     match attr_info {
         // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
-        Some((name, _, template, _)) if name != sym::rustc_dummy => {
-            check_builtin_attribute(sess, attr, name, template)
+        Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
+            check_builtin_attribute(sess, attr, *name, *template)
         }
         _ if let MacArgs::Eq(..) = attr.get_normal_item().args => {
             // All key-value attributes are restricted to meta-item syntax.
@@ -168,7 +167,7 @@ pub fn emit_fatal_malformed_builtin_attribute(
     attr: &Attribute,
     name: Symbol,
 ) -> ! {
-    let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").2;
+    let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template;
     emit_malformed_attribute(sess, attr, name, template);
     // This is fatal, otherwise it will likely cause a cascade of other errors
     // (and an error here is expected to be very rare).
index 596d13d2d9acbb7aa8c79b2f79820e88f76db106..129a9fdab8234aa08febbe6d49976f008b2f2e94 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability};
-use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP};
+use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -148,7 +148,7 @@ fn check_attributes(
             }
 
             if hir_id != CRATE_HIR_ID {
-                if let Some((_, AttributeType::CrateLevel, ..)) =
+                if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) =
                     attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
                 {
                     self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
index a0ceb567f25a6f8d13b6d04bc860153e86a3c478..82486a6a5f2e277a75b639edd84c5127e1af0750 100644 (file)
@@ -210,10 +210,10 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
             required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
 
         match missing_gates.as_slice() {
-            &[] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(),
+            [] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(),
 
-            &[missing_primary, ref missing_secondary @ ..] => {
-                let mut err = feature_err(&tcx.sess.parse_sess, missing_primary, span, &msg);
+            [missing_primary, ref missing_secondary @ ..] => {
+                let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg);
 
                 // If multiple feature gates would be required to enable this expression, include
                 // them as help messages. Don't emit a separate error for each missing feature gate.
index 5fc8e230d72a3eba67aca78d8a258115f9d21e31..6a8feb041da19f5978c4cf6055f79e127bf61ffc 100644 (file)
@@ -334,9 +334,10 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
     // properly, we can't miss any types.
 
     match expr.kind {
-        // Manually recurse over closures, because they are the only
+        // Manually recurse over closures and inline consts, because they are the only
         // case of nested bodies that share the parent environment.
-        hir::ExprKind::Closure(.., body, _, _) => {
+        hir::ExprKind::Closure(.., body, _, _)
+        | hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => {
             let body = visitor.tcx.hir().body(body);
             visitor.visit_body(body);
         }
@@ -817,9 +818,9 @@ fn visit_local(&mut self, l: &'tcx Local<'tcx>) {
 }
 
 fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
-    let closure_base_def_id = tcx.closure_base_def_id(def_id);
-    if closure_base_def_id != def_id {
-        return tcx.region_scope_tree(closure_base_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+    if typeck_root_def_id != def_id {
+        return tcx.region_scope_tree(typeck_root_def_id);
     }
 
     let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
index fa34b9abc1e6c9314288ae045f6d1e71dde8ec03..11668146f7b105560054110ed66e1c3d2cdd79f7 100644 (file)
@@ -543,7 +543,7 @@ fn update_macro_reachable_def(
         module: LocalDefId,
     ) {
         let level = Some(AccessLevel::Reachable);
-        if let ty::Visibility::Public = vis {
+        if vis.is_public() {
             self.update(def_id, level);
         }
         match def_kind {
@@ -580,7 +580,7 @@ fn update_macro_reachable_def(
 
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
-                if let ty::Visibility::Public = vis {
+                if vis.is_public() {
                     let item =
                         self.tcx.hir().expect_item(self.tcx.hir().local_def_id_to_hir_id(def_id));
                     if let hir::ItemKind::Struct(ref struct_def, _)
@@ -618,6 +618,7 @@ fn update_macro_reachable_def(
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::Field
             | DefKind::GlobalAsm
             | DefKind::Impl
@@ -932,7 +933,7 @@ fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _sp: Span, id: hir::HirId) {
             let def_id = self.tcx.hir().local_def_id(id);
             if let Some(exports) = self.tcx.module_exports(def_id) {
                 for export in exports.iter() {
-                    if export.vis == ty::Visibility::Public {
+                    if export.vis.is_public() {
                         if let Some(def_id) = export.res.opt_def_id() {
                             if let Some(def_id) = def_id.as_local() {
                                 self.update(def_id, Some(AccessLevel::Exported));
@@ -1917,8 +1918,7 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
     /// 1. It's contained within a public type
     /// 2. It comes from a private crate
     fn leaks_private_dep(&self, item_id: DefId) -> bool {
-        let ret = self.required_visibility == ty::Visibility::Public
-            && self.tcx.is_private_dep(item_id.krate);
+        let ret = self.required_visibility.is_public() && self.tcx.is_private_dep(item_id.krate);
 
         tracing::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
         ret
index 238b92a61342b451ce842a09e46a8fc925a00de2..9703f0c3d9605269089498686272447cc188bb9e 100644 (file)
@@ -518,9 +518,22 @@ fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
         if let Some(result) = result {
+            let prev_fingerprint = tcx
+                .dep_context()
+                .dep_graph()
+                .prev_fingerprint_of(dep_node)
+                .unwrap_or(Fingerprint::ZERO);
             // If `-Zincremental-verify-ich` is specified, re-hash results from
             // the cache and make sure that they have the expected fingerprint.
-            if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
+            //
+            // If not, we still seek to verify a subset of fingerprints loaded
+            // from disk. Re-hashing results is fairly expensive, so we can't
+            // currently afford to verify every hash. This subset should still
+            // give us some coverage of potential bugs though.
+            let try_verify = prev_fingerprint.as_value().1 % 32 == 0;
+            if unlikely!(
+                try_verify || tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich
+            ) {
                 incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
             }
 
index 33af9884cbb6686ced37c2729251fdb5094491e1..3cf9d324a38da9d2272d4d6c07321d95d5e57330 100644 (file)
@@ -15,7 +15,7 @@
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
-use rustc_ast::{Block, FnKind, ForeignItem, ForeignItemKind, ImplKind, Item, ItemKind, NodeId};
+use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_attr as attr;
 use rustc_data_structures::sync::Lrc;
@@ -880,7 +880,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
             }
 
             // These items do not add names to modules.
-            ItemKind::Impl(box ImplKind { of_trait: Some(..), .. }) => {
+            ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
                 self.r.trait_impl_items.insert(local_def_id);
             }
             ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
@@ -967,6 +967,7 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) {
                 | DefKind::Use
                 | DefKind::ForeignMod
                 | DefKind::AnonConst
+                | DefKind::InlineConst
                 | DefKind::Field
                 | DefKind::LifetimeParam
                 | DefKind::GlobalAsm
@@ -1193,15 +1194,9 @@ fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)>
     // Mark the given macro as unused unless its name starts with `_`.
     // Macro uses will remove items from this set, and the remaining
     // items will be reported as `unused_macros`.
-    fn insert_unused_macro(
-        &mut self,
-        ident: Ident,
-        def_id: LocalDefId,
-        node_id: NodeId,
-        span: Span,
-    ) {
+    fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: NodeId) {
         if !ident.as_str().starts_with('_') {
-            self.r.unused_macros.insert(def_id, (node_id, span));
+            self.r.unused_macros.insert(def_id, (node_id, ident));
         }
     }
 
@@ -1245,7 +1240,7 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
                 self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport));
             } else {
                 self.r.check_reserved_macro_name(ident, res);
-                self.insert_unused_macro(ident, def_id, item.id, span);
+                self.insert_unused_macro(ident, def_id, item.id);
             }
             self.r.visibilities.insert(def_id, vis);
             self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding(
@@ -1266,7 +1261,7 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
                 _ => self.resolve_visibility(&item.vis),
             };
             if vis != ty::Visibility::Public {
-                self.insert_unused_macro(ident, def_id, item.id, span);
+                self.insert_unused_macro(ident, def_id, item.id);
             }
             self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
             self.r.visibilities.insert(def_id, vis);
@@ -1380,7 +1375,7 @@ fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {
         if ctxt == AssocCtxt::Trait {
             let (def_kind, ns) = match item.kind {
                 AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS),
-                AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) => {
+                AssocItemKind::Fn(box Fn { ref sig, .. }) => {
                     if sig.decl.has_self() {
                         self.r.has_self.insert(def_id);
                     }
index 760b74699619619e8bd4969163ba8d93ebefbfba..63699128e9e1627ebbe2e36f83435db6a1489e9b 100644 (file)
@@ -32,7 +32,6 @@
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::pluralize;
-use rustc_middle::ty;
 use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
@@ -228,7 +227,7 @@ impl Resolver<'_> {
         for import in self.potentially_unused_imports.iter() {
             match import.kind {
                 _ if import.used.get()
-                    || import.vis.get() == ty::Visibility::Public
+                    || import.vis.get().is_public()
                     || import.span.is_dummy() =>
                 {
                     if let ImportKind::MacroUse = import.kind {
index ff0d76e94fdf5c231a8b8f193e034c4a0d4201f1..c46a18e51031abd33a261a31a0f84a99d088f026 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::PrimTy;
 use rustc_middle::bug;
-use rustc_middle::ty::{self, DefIdTree};
+use rustc_middle::ty::DefIdTree;
 use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -731,7 +731,7 @@ fn early_lookup_typo_candidate(
                         suggestions.extend(
                             BUILTIN_ATTRIBUTES
                                 .iter()
-                                .map(|(name, ..)| TypoSuggestion::typo_from_res(*name, res)),
+                                .map(|attr| TypoSuggestion::typo_from_res(attr.name, res)),
                         );
                     }
                 }
@@ -1308,7 +1308,7 @@ fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
             );
             let def_span = self.session.source_map().guess_head_span(binding.span);
             let mut note_span = MultiSpan::from_span(def_span);
-            if !first && binding.vis == ty::Visibility::Public {
+            if !first && binding.vis.is_public() {
                 note_span.push_span_label(def_span, "consider importing it directly".into());
             }
             err.span_note(note_span, &msg);
index 936ab81914a99be5cfe57cf9b900c46d96d1e606..4262c1e9051ee57a1694c34aab3281198c4edf81 100644 (file)
@@ -164,7 +164,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi
                 import: Import { kind: ImportKind::ExternCrate { .. }, .. },
                 ..
             },
-        ) => import.vis.get() == ty::Visibility::Public,
+        ) => import.vis.get().is_public(),
         _ => false,
     }
 }
index 0a24e00ee4bf5137b88eadef81b20a09266b4ebb..e67f7f03516803c0a7cb7ca7acfb57b9f05f4846 100644 (file)
@@ -498,8 +498,8 @@ fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBound
     }
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         match foreign_item.kind {
-            ForeignItemKind::Fn(box FnKind(_, _, ref generics, _))
-            | ForeignItemKind::TyAlias(box TyAliasKind(_, ref generics, ..)) => {
+            ForeignItemKind::Fn(box Fn { ref generics, .. })
+            | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
@@ -953,8 +953,8 @@ fn resolve_item(&mut self, item: &'ast Item) {
         debug!("(resolving item) resolving {} ({:?})", name, item.kind);
 
         match item.kind {
-            ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, _))
-            | ItemKind::Fn(box FnKind(_, _, ref generics, _)) => {
+            ItemKind::TyAlias(box TyAlias { ref generics, .. })
+            | ItemKind::Fn(box Fn { ref generics, .. }) => {
                 self.compute_num_lifetime_params(item.id, generics);
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_item(this, item)
@@ -968,7 +968,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
                 self.resolve_adt(item, generics);
             }
 
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 ref generics,
                 ref of_trait,
                 ref self_ty,
@@ -979,7 +979,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
                 self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
             }
 
-            ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref trait_items)) => {
+            ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
                 self.compute_num_lifetime_params(item.id, generics);
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
@@ -994,8 +994,8 @@ fn resolve_item(&mut self, item: &'ast Item) {
                             });
                         };
 
-                        this.with_trait_items(trait_items, |this| {
-                            for item in trait_items {
+                        this.with_trait_items(items, |this| {
+                            for item in items {
                                 match &item.kind {
                                     AssocItemKind::Const(_, ty, default) => {
                                         this.visit_ty(ty);
@@ -1015,10 +1015,10 @@ fn resolve_item(&mut self, item: &'ast Item) {
                                             );
                                         }
                                     }
-                                    AssocItemKind::Fn(box FnKind(_, _, generics, _)) => {
+                                    AssocItemKind::Fn(box Fn { generics, .. }) => {
                                         walk_assoc_item(this, generics, item);
                                     }
-                                    AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, _)) => {
+                                    AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
                                         walk_assoc_item(this, generics, item);
                                     }
                                     AssocItemKind::MacCall(_) => {
@@ -1338,7 +1338,7 @@ fn resolve_implementation(
                                                 },
                                             );
                                         }
-                                        AssocItemKind::Fn(box FnKind(.., generics, _)) => {
+                                        AssocItemKind::Fn(box Fn { generics, .. }) => {
                                             debug!("resolve_implementation AssocItemKind::Fn");
                                             // We also need a new scope for the impl item type parameters.
                                             this.with_generic_param_rib(
@@ -1363,12 +1363,9 @@ fn resolve_implementation(
                                                 },
                                             );
                                         }
-                                        AssocItemKind::TyAlias(box TyAliasKind(
-                                            _,
-                                            generics,
-                                            _,
-                                            _,
-                                        )) => {
+                                        AssocItemKind::TyAlias(box TyAlias {
+                                            generics, ..
+                                        }) => {
                                             debug!("resolve_implementation AssocItemKind::TyAlias");
                                             // We also need a new scope for the impl item type parameters.
                                             this.with_generic_param_rib(
index 5f90fcdfa64e2cc205525adfa782b98bdb29484b..4acbb11b13f76295a290e49519088776416e605b 100644 (file)
@@ -333,7 +333,7 @@ pub(crate) fn smart_resolve_report_errors(
         let candidates = self
             .r
             .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
-            .drain(..)
+            .into_iter()
             .filter(|ImportSuggestion { did, .. }| {
                 match (did, res.and_then(|res| res.opt_def_id())) {
                     (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did,
@@ -1235,9 +1235,7 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
                 if assoc_item.ident == ident {
                     return Some(match &assoc_item.kind {
                         ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
-                        ast::AssocItemKind::Fn(box ast::FnKind(_, sig, ..))
-                            if sig.decl.has_self() =>
-                        {
+                        ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
                             AssocSuggestion::MethodWithSelf
                         }
                         ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn,
@@ -1346,12 +1344,10 @@ fn lookup_typo_candidate(
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
-            if let PathResult::Module(module) =
+            if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
                 self.resolve_path(mod_path, Some(TypeNS), false, span, CrateLint::No)
             {
-                if let ModuleOrUniformRoot::Module(module) = module {
-                    self.r.add_module_candidates(module, &mut names, &filter_fn);
-                }
+                self.r.add_module_candidates(module, &mut names, &filter_fn);
             }
         }
 
@@ -1554,7 +1550,7 @@ fn suggest_using_enum_variant(
         if suggest_only_tuple_variants {
             // Suggest only tuple variants regardless of whether they have fields and do not
             // suggest path with added parentheses.
-            let mut suggestable_variants = variants
+            let suggestable_variants = variants
                 .iter()
                 .filter(|(.., kind)| *kind == CtorKind::Fn)
                 .map(|(variant, ..)| path_names_to_string(variant))
@@ -1580,7 +1576,7 @@ fn suggest_using_enum_variant(
                 err.span_suggestions(
                     span,
                     &msg,
-                    suggestable_variants.drain(..),
+                    suggestable_variants.into_iter(),
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -1638,7 +1634,7 @@ fn suggest_using_enum_variant(
                 );
             }
 
-            let mut suggestable_variants_with_placeholders = variants
+            let suggestable_variants_with_placeholders = variants
                 .iter()
                 .filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
                 .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
@@ -1663,7 +1659,7 @@ fn suggest_using_enum_variant(
                 err.span_suggestions(
                     span,
                     msg,
-                    suggestable_variants_with_placeholders.drain(..),
+                    suggestable_variants_with_placeholders.into_iter(),
                     Applicability::HasPlaceholders,
                 );
             }
index 94563400a8b53580578424ca2251b4169e3c4391..39e710cb77f3fafd9129d6ad80061aea48ef3837 100644 (file)
@@ -540,7 +540,7 @@ fn is_late_bound_map<'tcx>(
     def_id: LocalDefId,
 ) -> Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
     match tcx.def_kind(def_id) {
-        DefKind::AnonConst => {
+        DefKind::AnonConst | DefKind::InlineConst => {
             let mut def_id = tcx
                 .parent(def_id.to_def_id())
                 .unwrap_or_else(|| bug!("anon const or closure without a parent"));
@@ -887,10 +887,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                 let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) = c
                     .generic_params
                     .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => Some(param),
-                        _ => None,
-                    })
+                    .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
                     .enumerate()
                     .map(|(late_bound_idx, param)| {
                         let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
@@ -1370,9 +1367,8 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
                         let (lifetimes, binders): (FxIndexMap<hir::ParamName, Region>, Vec<_>) =
                             bound_generic_params
                                 .iter()
-                                .filter_map(|param| match param.kind {
-                                    GenericParamKind::Lifetime { .. } => Some(param),
-                                    _ => None,
+                                .filter(|param| {
+                                    matches!(param.kind, GenericParamKind::Lifetime { .. })
                                 })
                                 .enumerate()
                                 .map(|(late_bound_idx, param)| {
@@ -1469,10 +1465,7 @@ fn visit_poly_trait_ref(
         let binders_iter = trait_ref
             .bound_generic_params
             .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. } => Some(param),
-                _ => None,
-            })
+            .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
             .enumerate()
             .map(|(late_bound_idx, param)| {
                 let pair = Region::late(
@@ -1931,20 +1924,18 @@ fn suggest_eliding_single_use_lifetime(
                             break;
                         }
                     }
-                    hir::TyKind::Path(ref qpath) => {
-                        if let QPath::Resolved(_, path) = qpath {
-                            let last_segment = &path.segments[path.segments.len() - 1];
-                            let generics = last_segment.args();
-                            for arg in generics.args.iter() {
-                                if let GenericArg::Lifetime(lt) = arg {
-                                    if lt.name.ident() == name {
-                                        elide_use = Some(lt.span);
-                                        break;
-                                    }
+                    hir::TyKind::Path(QPath::Resolved(_, path)) => {
+                        let last_segment = &path.segments[path.segments.len() - 1];
+                        let generics = last_segment.args();
+                        for arg in generics.args.iter() {
+                            if let GenericArg::Lifetime(lt) = arg {
+                                if lt.name.ident() == name {
+                                    elide_use = Some(lt.span);
+                                    break;
                                 }
                             }
-                            break;
                         }
+                        break;
                     }
                     _ => {}
                 }
@@ -2237,19 +2228,14 @@ fn visit_early_late<F>(
         let binders: Vec<_> = generics
             .params
             .iter()
-            .filter_map(|param| match param.kind {
-                GenericParamKind::Lifetime { .. }
-                    if self.map.late_bound.contains(&param.hir_id) =>
-                {
-                    Some(param)
-                }
-                _ => None,
+            .filter(|param| {
+                matches!(param.kind, GenericParamKind::Lifetime { .. })
+                    && self.map.late_bound.contains(&param.hir_id)
             })
             .enumerate()
             .map(|(late_bound_idx, param)| {
                 let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param);
-                let r = late_region_as_bound_region(self.tcx, &pair.1);
-                r
+                late_region_as_bound_region(self.tcx, &pair.1)
             })
             .collect();
         self.map.late_bound_vars.insert(hir_id, binders);
index 5f3620b247e26e1885a7361d282316268b84b1fb..f5bea83bdcf654f68aa8d109151ae573039ad1b7 100644 (file)
@@ -988,7 +988,7 @@ pub struct Resolver<'a> {
     non_macro_attr: Lrc<SyntaxExtension>,
     local_macro_def_scopes: FxHashMap<LocalDefId, Module<'a>>,
     ast_transform_scopes: FxHashMap<LocalExpnId, Module<'a>>,
-    unused_macros: FxHashMap<LocalDefId, (NodeId, Span)>,
+    unused_macros: FxHashMap<LocalDefId, (NodeId, Ident)>,
     proc_macro_stubs: FxHashSet<LocalDefId>,
     /// Traces collected during macro resolution and validated when it's complete.
     single_segment_macro_resolutions:
index 4f6e23d8f84f0e3fe40573d54c119e9f57ffa98e..31fd9b989e1c81827e523e30c52c8ad71018989f 100644 (file)
@@ -315,8 +315,13 @@ fn resolve_macro_invocation(
     }
 
     fn check_unused_macros(&mut self) {
-        for (_, &(node_id, span)) in self.unused_macros.iter() {
-            self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition");
+        for (_, &(node_id, ident)) in self.unused_macros.iter() {
+            self.lint_buffer.buffer_lint(
+                UNUSED_MACROS,
+                node_id,
+                ident.span,
+                &format!("unused macro definition: `{}`", ident.as_str()),
+            );
         }
     }
 
index 543cd0247a53daecd9400c4b4711a6232c54578a..c7f8fe3a88a64b1dc4ea99a8456f852f54083995 100644 (file)
@@ -739,6 +739,7 @@ fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
                 | HirDefKind::ForeignMod
                 | HirDefKind::LifetimeParam
                 | HirDefKind::AnonConst
+                | HirDefKind::InlineConst
                 | HirDefKind::Use
                 | HirDefKind::Field
                 | HirDefKind::GlobalAsm
index 299dfed9d5dcea7845f2898b3cb612e1ddc96d80..3afe094733928e0337843927531357c5892417f6 100644 (file)
@@ -578,6 +578,7 @@ pub struct OutputFilenames {
     pub out_directory: PathBuf,
     filestem: String,
     pub single_output_file: Option<PathBuf>,
+    pub temps_directory: Option<PathBuf>,
     pub outputs: OutputTypes,
 }
 
@@ -592,12 +593,14 @@ pub fn new(
         out_directory: PathBuf,
         out_filestem: String,
         single_output_file: Option<PathBuf>,
+        temps_directory: Option<PathBuf>,
         extra: String,
         outputs: OutputTypes,
     ) -> Self {
         OutputFilenames {
             out_directory,
             single_output_file,
+            temps_directory,
             outputs,
             filestem: format!("{}{}", out_filestem, extra),
         }
@@ -608,7 +611,14 @@ pub fn path(&self, flavor: OutputType) -> PathBuf {
             .get(&flavor)
             .and_then(|p| p.to_owned())
             .or_else(|| self.single_output_file.clone())
-            .unwrap_or_else(|| self.temp_path(flavor, None))
+            .unwrap_or_else(|| self.output_path(flavor))
+    }
+
+    /// Gets the output path where a compilation artifact of the given type
+    /// should be placed on disk.
+    pub fn output_path(&self, flavor: OutputType) -> PathBuf {
+        let extension = flavor.extension();
+        self.with_directory_and_extension(&self.out_directory, &extension)
     }
 
     /// Gets the path where a compilation artifact of the given type for the
@@ -643,11 +653,17 @@ pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathB
             extension.push_str(ext);
         }
 
-        self.with_extension(&extension)
+        let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
+
+        self.with_directory_and_extension(&temps_directory, &extension)
     }
 
     pub fn with_extension(&self, extension: &str) -> PathBuf {
-        let mut path = self.out_directory.join(&self.filestem);
+        self.with_directory_and_extension(&self.out_directory, extension)
+    }
+
+    fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf {
+        let mut path = directory.join(&self.filestem);
         path.set_extension(extension);
         path
     }
@@ -914,7 +930,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo
 pub(super) fn build_target_config(
     opts: &Options,
     target_override: Option<Target>,
-    sysroot: &PathBuf,
+    sysroot: &Path,
 ) -> Target {
     let target_result = target_override.map_or_else(
         || Target::search(&opts.target_triple, sysroot),
index 3add3e861484e82b862ec6f156497847143fa6ad..d1d8606a75a45db4af76e2dbc01f3f5fe26ba76a 100644 (file)
@@ -881,7 +881,7 @@ mod parse {
         match v {
             Some(s) => {
                 if !slot.is_empty() {
-                    slot.push_str(",");
+                    slot.push(',');
                 }
                 slot.push_str(s);
                 true
@@ -1331,6 +1331,8 @@ mod parse {
         "which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
     teach: bool = (false, parse_bool, [TRACKED],
         "show extended diagnostic help (default: no)"),
+    temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
+        "the directory the intermediate files are written to"),
     terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
         "set the current terminal width"),
     tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
index 0f6a3ddccbaf0fbc62628cdb6d16b234c038b2be..74b3cfa44c31aaa0e8847ddd5705daa841566e62 100644 (file)
@@ -411,7 +411,7 @@ pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
     pub fn compile_status(&self) -> Result<(), ErrorReported> {
-        if self.has_errors() {
+        if self.diagnostic().has_errors_or_lint_errors() {
             self.diagnostic().emit_stashed_diagnostics();
             Err(ErrorReported)
         } else {
index 032ae73bbf3c61fe503de4442584f5fc658a0e2b..dfc64f37e4c46b84c7e1ee9a02ee1282a6feba67 100644 (file)
@@ -194,10 +194,8 @@ fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
         encoder.emit_enum(|encoder| match *self {
             RealFileName::LocalPath(ref local_path) => {
                 encoder.emit_enum_variant("LocalPath", 0, 1, |encoder| {
-                    Ok({
-                        encoder
-                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
-                    })
+                    encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+                    Ok(())
                 })
             }
 
@@ -206,12 +204,9 @@ fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
                     // For privacy and build reproducibility, we must not embed host-dependant path in artifacts
                     // if they have been remapped by --remap-path-prefix
                     assert!(local_path.is_none());
-                    Ok({
-                        encoder
-                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
-                        encoder
-                            .emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
-                    })
+                    encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+                    encoder.emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
+                    Ok(())
                 }),
         })
     }
index 52e2a8f48e23be3f62f4f419d1ba34e7359c5b82..99fa9f000944df2b6e66f6227ac44f85105641dd 100644 (file)
         __S,
         __next,
         __try_var,
+        _args,
         _d,
         _e,
         _task_context,
         as_ptr,
         as_str,
         asm,
+        asm_const,
+        asm_experimental_arch,
+        asm_sym,
         assert,
         assert_inhabited,
         assert_macro,
index 01f5c197d2023c477d14277c129d0f2281da8d02..afe8bbb352886a214d1b8bb7f3fd3c3d130b6000 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, RelocModel, Target, TargetOptions};
 
 /// A base target for Nintendo 3DS devices using the devkitARM toolchain.
 ///
@@ -36,7 +36,6 @@ pub fn target() -> Target {
             features: "+vfp2".to_string(),
             pre_link_args,
             exe_suffix: ".elf".to_string(),
-            panic_strategy: PanicStrategy::Abort,
             ..Default::default()
         },
     }
index 0b95d1ca851a16fd593b41427edb6fa0f829b5ae..69b90bf10fe6a131d3c96e6da2b27d1db190ffe1 100644 (file)
@@ -2071,7 +2071,7 @@ macro_rules! key {
     /// JSON decoding.
     pub fn search(
         target_triple: &TargetTriple,
-        sysroot: &PathBuf,
+        sysroot: &Path,
     ) -> Result<(Target, TargetWarnings), String> {
         use rustc_serialize::json;
         use std::env;
index 53afe4ca068c4cf24f0601ee3c38ddb7a8cbc855..4c80483fc1f1e7750b5c3e68200c75ccb6a6ec23 100644 (file)
@@ -152,11 +152,12 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
             },
             cause,
         );
-        if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
+        let errors = fulfillcx.select_where_possible(&self.infcx);
+        if !errors.is_empty() {
             // This shouldn't happen, except for evaluate/fulfill mismatches,
             // but that's not a reason for an ICE (`predicate_may_hold` is conservative
             // by design).
-            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e);
+            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
             return None;
         }
         let obligations = fulfillcx.pending_obligations();
index 6452b520452d6802b157c023ecf457620a3da1c3..54f7b91080dd9fb0a9cae74dea7ecd43517972a5 100644 (file)
@@ -187,9 +187,11 @@ pub fn find_auto_trait_generics<A>(
             // an additional sanity check.
             let mut fulfill = FulfillmentContext::new();
             fulfill.register_bound(&infcx, full_env, ty, trait_did, ObligationCause::dummy());
-            fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
-                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
-            });
+            let errors = fulfill.select_all_or_error(&infcx);
+
+            if !errors.is_empty() {
+                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
+            }
 
             let body_id_map: FxHashMap<_, _> = infcx
                 .inner
index ec62ee400688ca2f62cae140fc32b1f40da8bf5e..2ccb25349173ff300d88e636ad59848fcad44e92 100644 (file)
@@ -49,34 +49,32 @@ fn register_predicate_obligation(
         self.obligations.insert(obligation);
     }
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        if self.obligations.is_empty() {
-            Ok(())
-        } else {
-            let errors = self
-                .obligations
-                .iter()
-                .map(|obligation| FulfillmentError {
-                    obligation: obligation.clone(),
-                    code: FulfillmentErrorCode::CodeAmbiguity,
-                    // FIXME - does Chalk have a notation of 'root obligation'?
-                    // This is just for diagnostics, so it's okay if this is wrong
-                    root_obligation: obligation.clone(),
-                })
-                .collect();
-            Err(errors)
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_where_possible(infcx);
+
+            if !errors.is_empty() {
+                return errors;
+            }
         }
+
+        // any remaining obligations are errors
+        self.obligations
+            .iter()
+            .map(|obligation| FulfillmentError {
+                obligation: obligation.clone(),
+                code: FulfillmentErrorCode::CodeAmbiguity,
+                // FIXME - does Chalk have a notation of 'root obligation'?
+                // This is just for diagnostics, so it's okay if this is wrong
+                root_obligation: obligation.clone(),
+            })
+            .collect()
     }
 
     fn select_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         assert!(!infcx.is_in_snapshot());
 
         let mut errors = Vec::new();
@@ -147,7 +145,7 @@ fn select_where_possible(
             }
         }
 
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+        errors
     }
 
     fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
index f06f0e32f414b73f90e35192996ba41ba780fcb3..bdd4fdd40438c6fb5e4ce219847bd106146f559a 100644 (file)
@@ -120,7 +120,8 @@ fn drain_fulfillment_cx_or_panic<T>(
     // In principle, we only need to do this so long as `result`
     // contains unbound type parameters. It could be a slight
     // optimization to stop iterating early.
-    if let Err(errors) = fulfill_cx.select_all_or_error(infcx) {
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
         infcx.tcx.sess.delay_span_bug(
             rustc_span::DUMMY_SP,
             &format!("Encountered errors `{:?}` resolving bounds after type-checking", errors),
index 8edb7069fc45f9a19c55f3c66f75a0bc79b9870f..6b5d37c0f43086516d57425d66807dd3b6ca72b7 100644 (file)
@@ -151,7 +151,7 @@ enum FailureKind {
 
     if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) {
         match infcx.tcx.def_kind(uv.def.did) {
-            DefKind::AnonConst => {
+            DefKind::AnonConst | DefKind::InlineConst => {
                 let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
 
                 if mir_body.is_polymorphic {
@@ -495,7 +495,7 @@ pub(super) fn thir_abstract_const<'tcx>(
             // we want to look into them or treat them as opaque projections.
             //
             // Right now we do neither of that and simply always fail to unify them.
-            DefKind::AnonConst => (),
+            DefKind::AnonConst | DefKind::InlineConst => (),
             _ => return Ok(None),
         }
 
index a9125b9fd2280ed259e52e0dcffccc54ce941169..79194718d1efd5da0289d6f6bd8ea7e72059fcb0 100644 (file)
@@ -266,19 +266,16 @@ fn report_selection_error(
                     }
                 }
                 if let ObligationCauseCode::CompareImplMethodObligation {
-                    item_name,
                     impl_item_def_id,
                     trait_item_def_id,
                 }
                 | ObligationCauseCode::CompareImplTypeObligation {
-                    item_name,
                     impl_item_def_id,
                     trait_item_def_id,
                 } = obligation.cause.code
                 {
                     self.report_extra_impl_obligation(
                         span,
-                        item_name,
                         impl_item_def_id,
                         trait_item_def_id,
                         &format!("`{}`", obligation.predicate),
@@ -2000,19 +1997,14 @@ fn maybe_suggest_unsized_generics(
         let sized_trait = self.tcx.lang_items().sized_trait();
         debug!("maybe_suggest_unsized_generics: generics.params={:?}", generics.params);
         debug!("maybe_suggest_unsized_generics: generics.where_clause={:?}", generics.where_clause);
-        let param = generics
-            .params
-            .iter()
-            .filter(|param| param.span == span)
-            .filter(|param| {
-                // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
-                // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
-                param
-                    .bounds
-                    .iter()
-                    .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
-            })
-            .next();
+        let param = generics.params.iter().filter(|param| param.span == span).find(|param| {
+            // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
+            // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
+            param
+                .bounds
+                .iter()
+                .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
+        });
         let param = match param {
             Some(param) => param,
             _ => return,
index 2689e2134fc6b5e0ded2dd2e01f732375f0e4424..7d9568e0ca3526d21dc9053ac91ca3b92cee715d 100644 (file)
@@ -1474,7 +1474,7 @@ fn maybe_note_obligation_cause_for_async_await(
         let span = self.tcx.def_span(generator_did);
 
         let in_progress_typeck_results = self.in_progress_typeck_results.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
         debug!(
             "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
              generator_did_root={:?} in_progress_typeck_results.hir_owner={:?} span={:?}",
@@ -2354,11 +2354,8 @@ fn note_obligation_cause_code<T>(
                     )
                 });
             }
-            ObligationCauseCode::CompareImplMethodObligation {
-                item_name,
-                trait_item_def_id,
-                ..
-            } => {
+            ObligationCauseCode::CompareImplMethodObligation { trait_item_def_id, .. } => {
+                let item_name = self.tcx.item_name(trait_item_def_id);
                 let msg = format!(
                     "the requirement `{}` appears on the impl method `{}` but not on the \
                      corresponding trait method",
@@ -2383,9 +2380,8 @@ fn note_obligation_cause_code<T>(
                 }
                 err.span_note(assoc_span, &msg);
             }
-            ObligationCauseCode::CompareImplTypeObligation {
-                item_name, trait_item_def_id, ..
-            } => {
+            ObligationCauseCode::CompareImplTypeObligation { trait_item_def_id, .. } => {
+                let item_name = self.tcx.item_name(trait_item_def_id);
                 let msg = format!(
                     "the requirement `{}` appears on the associated impl type `{}` but not on the \
                      corresponding associated trait type",
index 465d1465d5d3538325def6ae9dcf226b730f9aa6..e121837c987ae9b694ea1b45281abca63da8e8c7 100644 (file)
@@ -126,10 +126,7 @@ pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
     }
 
     /// Attempts to select obligations using `selcx`.
-    fn select(
-        &mut self,
-        selcx: &mut SelectionContext<'a, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
         let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
         let _enter = span.enter();
 
@@ -163,7 +160,7 @@ fn select(
             errors.len()
         );
 
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+        errors
     }
 }
 
@@ -223,41 +220,36 @@ fn register_predicate_obligation(
             .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
     }
 
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(to_fulfillment_error)
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_where_possible(infcx);
+            if !errors.is_empty() {
+                return errors;
+            }
+        }
+
+        self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
     }
 
     fn select_all_with_constness_or_error(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         constness: rustc_hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_with_constness_where_possible(infcx, constness)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(to_fulfillment_error)
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
+    ) -> Vec<FulfillmentError<'tcx>> {
+        {
+            let errors = self.select_with_constness_where_possible(infcx, constness);
+            if !errors.is_empty() {
+                return errors;
+            }
+        }
+
+        self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
     }
 
     fn select_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         let mut selcx = SelectionContext::new(infcx);
         self.select(&mut selcx)
     }
@@ -266,7 +258,7 @@ fn select_with_constness_where_possible(
         &mut self,
         infcx: &InferCtxt<'_, 'tcx>,
         constness: hir::Constness,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
+    ) -> Vec<FulfillmentError<'tcx>> {
         let mut selcx = SelectionContext::with_constness(infcx, constness);
         self.select(&mut selcx)
     }
index cedd1aa54b876ff5bec787ff57a7080e5c025d1a..fa8890fc352929e062f75d7b4f4788599a577fae 100644 (file)
@@ -33,7 +33,8 @@ pub fn can_type_implement_copy(
             | ty::Char
             | ty::RawPtr(..)
             | ty::Never
-            | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
+            | ty::Ref(_, _, hir::Mutability::Not)
+            | ty::Array(..) => return Ok(()),
 
             ty::Adt(adt, substs) => (adt, substs),
 
index 8f247184e880873d6f1d4a1419ee959c2753b16e..d4a586b0124a20b1bd790bebc98f0ccc991f0611 100644 (file)
@@ -180,8 +180,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
         // Note: we only assume something is `Copy` if we can
         // *definitively* show that it implements `Copy`. Otherwise,
         // assume it is move; linear is always ok.
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => {
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => {
                 debug!(
                     "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
                     ty,
@@ -189,12 +189,12 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
                 );
                 true
             }
-            Err(e) => {
+            errors => {
                 debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
-                    ty,
-                    infcx.tcx.def_path_str(def_id),
-                    e
+                    ?ty,
+                    bound = %infcx.tcx.def_path_str(def_id),
+                    ?errors,
+                    "type_known_to_meet_bound_modulo_regions"
                 );
                 false
             }
@@ -410,7 +410,10 @@ pub fn fully_normalize<'a, 'tcx, T>(
     }
 
     debug!("fully_normalize: select_all_or_error start");
-    fulfill_cx.select_all_or_error(infcx)?;
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
+        return Err(errors);
+    }
     debug!("fully_normalize: select_all_or_error complete");
     let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
     debug!("fully_normalize: resolved_value={:?}", resolved_value);
@@ -441,7 +444,9 @@ pub fn impossible_predicates<'tcx>(
             fulfill_cx.register_predicate_obligation(&infcx, obligation);
         }
 
-        fulfill_cx.select_all_or_error(&infcx).is_err()
+        let errors = fulfill_cx.select_all_or_error(&infcx);
+
+        !errors.is_empty()
     });
     debug!("impossible_predicates = {:?}", result);
     result
index b5398f8a4353b222599a49f008bb91a8ccc47035..0a85676f4315e36a88893a759201e899d87b0754 100644 (file)
@@ -77,10 +77,11 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
     debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
     fulfill_cx.register_predicate_obligations(infcx, obligations);
-    if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
+    let errors = fulfill_cx.select_all_or_error(infcx);
+    if !errors.is_empty() {
         infcx.tcx.sess.diagnostic().delay_span_bug(
             DUMMY_SP,
-            &format!("errors selecting obligation during MIR typeck: {:?}", e),
+            &format!("errors selecting obligation during MIR typeck: {:?}", errors),
         );
     }
 
index 60676ad3f4f606b9cec87aec869d4083b539f098..2aa214694cb1472cd54827befdd2ee2b50a0b7d9 100644 (file)
@@ -320,10 +320,7 @@ pub fn is_intercrate(&self) -> bool {
 
     /// Returns `true` if the trait predicate is considerd `const` to this selection context.
     pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
-        match pred.constness {
-            ty::BoundConstness::ConstIfConst if self.is_in_const_context => true,
-            _ => false,
-        }
+        matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context
     }
 
     /// Returns `true` if the predicate is considered `const` to
@@ -1862,7 +1859,8 @@ fn copy_clone_conditions(
             | ty::Char
             | ty::RawPtr(..)
             | ty::Never
-            | ty::Ref(_, _, hir::Mutability::Not) => {
+            | ty::Ref(_, _, hir::Mutability::Not)
+            | ty::Array(..) => {
                 // Implementations provided in libcore
                 None
             }
@@ -1875,11 +1873,6 @@ fn copy_clone_conditions(
             | ty::Foreign(..)
             | ty::Ref(_, _, hir::Mutability::Mut) => None,
 
-            ty::Array(element_ty, _) => {
-                // (*) binder moved here
-                Where(obligation.predicate.rebind(vec![element_ty]))
-            }
-
             ty::Tuple(tys) => {
                 // (*) binder moved here
                 Where(obligation.predicate.rebind(tys.iter().map(|k| k.expect_ty()).collect()))
index f9867f0671e59fbd7478629fcd114f4dfea652de..b64c55592272ed07f63b2813a3a748ff7e2d8778 100644 (file)
@@ -225,8 +225,18 @@ fn fulfill_implication<'a, 'tcx>(
         for oblig in obligations.chain(more_obligations) {
             fulfill_cx.register_predicate_obligation(&infcx, oblig);
         }
-        match fulfill_cx.select_all_or_error(infcx) {
-            Err(errors) => {
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => {
+                debug!(
+                    "fulfill_implication: an impl for {:?} specializes {:?}",
+                    source_trait_ref, target_trait_ref
+                );
+
+                // Now resolve the *substitution* we built for the target earlier, replacing
+                // the inference variables inside with whatever we got from fulfillment.
+                Ok(infcx.resolve_vars_if_possible(target_substs))
+            }
+            errors => {
                 // no dice!
                 debug!(
                     "fulfill_implication: for impls on {:?} and {:?}, \
@@ -238,17 +248,6 @@ fn fulfill_implication<'a, 'tcx>(
                 );
                 Err(())
             }
-
-            Ok(()) => {
-                debug!(
-                    "fulfill_implication: an impl for {:?} specializes {:?}",
-                    source_trait_ref, target_trait_ref
-                );
-
-                // Now resolve the *substitution* we built for the target earlier, replacing
-                // the inference variables inside with whatever we got from fulfillment.
-                Ok(infcx.resolve_vars_if_possible(target_substs))
-            }
         }
     })
 }
@@ -292,6 +291,11 @@ pub(super) fn specialization_graph_provider(
     sg
 }
 
+// This function is only used when
+// encountering errors and inlining
+// it negatively impacts perf.
+#[cold]
+#[inline(never)]
 fn report_overlap_conflict(
     tcx: TyCtxt<'_>,
     overlap: OverlapError,
@@ -444,8 +448,12 @@ fn report_conflicting_impls(
     match used_to_be_allowed {
         None => {
             sg.has_errored = true;
-            let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
-            decorate(LintDiagnosticBuilder::new(err));
+            if overlap.with_impl.is_local() || !tcx.orphan_check_crate(()).contains(&impl_def_id) {
+                let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
+                decorate(LintDiagnosticBuilder::new(err));
+            } else {
+                tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check");
+            }
         }
         Some(kind) => {
             let lint = match kind {
index a398e847b935458a003fab06e30ed423802e255c..3d71382227868df2c1ccd43ddb0cbafa19ece152 100644 (file)
@@ -103,7 +103,7 @@ fn type_marked_structural(
     //
     // 2. We are sometimes doing future-incompatibility lints for
     //    now, so we do not want unconditional errors here.
-    fulfillment_cx.select_all_or_error(infcx).is_ok()
+    fulfillment_cx.select_all_or_error(infcx).is_empty()
 }
 
 /// This implements the traversal over the structure of a given type to try to
index 37e007337374fd2553af77fcff1f307c2062e2c1..92f2760e62c7e86ef62e460bc320126f73cb996d 100644 (file)
@@ -128,9 +128,9 @@ fn compute_implied_outlives_bounds<'tcx>(
 
     // Ensure that those obligations that we had to solve
     // get solved *here*.
-    match fulfill_cx.select_all_or_error(infcx) {
-        Ok(()) => Ok(implied_bounds),
-        Err(_) => Err(NoSolution),
+    match fulfill_cx.select_all_or_error(infcx).as_slice() {
+        [] => Ok(implied_bounds),
+        _ => Err(NoSolution),
     }
 }
 
index 87b729faa54e0ad5f34796d330d236b9270612e7..13ffb2a5adc860b39d3173db80afaace4b76f713 100644 (file)
@@ -362,7 +362,7 @@ fn resolve_associated_item<'tcx>(
                     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(..) => {}
+                        ty::Closure(..) | ty::Tuple(..) => {}
                         _ => return Ok(None),
                     };
 
index 84327a2880e18c6499eb4eaa82c41beaae735124..2f187997b55de0fbf10a7028524a44649b5d3a68 100644 (file)
@@ -672,6 +672,17 @@ pub(crate) fn check_impl_trait(
                 err.span_label(span, "explicit generic argument not allowed");
             }
 
+            err.note(
+                "see issue #83701 <https://github.com/rust-lang/rust/issues/83701> \
+                 for more information",
+            );
+            if tcx.sess.is_nightly_build() {
+                err.help(
+                    "add `#![feature(explicit_generic_args_with_impl_trait)]` \
+                     to the crate attributes to enable",
+                );
+            }
+
             err.emit();
         }
 
index 78849b276d6bfb80f610c574a021f4b7efb91d3a..511a2d7ddacf96e42f453690267c1094f0e995ef 100644 (file)
@@ -436,11 +436,8 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                     // Very crude check to see whether the expression must be wrapped
                     // in parentheses for the suggestion to work (issue #89497).
                     // Can/should be extended in the future.
-                    let needs_parens = !has_parens
-                        && match self.expr.kind {
-                            hir::ExprKind::Cast(..) => true,
-                            _ => false,
-                        };
+                    let needs_parens =
+                        !has_parens && matches!(self.expr.kind, hir::ExprKind::Cast(..));
 
                     let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
                     if needs_parens {
index 5040c4db95163a48473aace18608b6d7a7d55623..f0a77cb39a62273b1fb3a18e9faa091da3b20840 100644 (file)
@@ -663,8 +663,9 @@ fn check_opaque_meets_bounds<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
         }
 
         // Finally, resolve all regions. This catches wily misuses of
index 410ac24b1f19c84a8659e5186f31f5c264db201d..f7accbb430caae8375fb5a6c318244009f0b15d7 100644 (file)
@@ -92,7 +92,7 @@ fn check_closure(
 
         let parent_substs = InternalSubsts::identity_for_item(
             self.tcx,
-            self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
+            self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
         );
 
         let tupled_upvars_ty = self.infcx.next_ty_var(TypeVariableOrigin {
index ad65a0ba62a8cc8b0372214abbc2da99f575a96c..28712e0658269d5338fdd39ace5c3a713cc6838e 100644 (file)
@@ -950,7 +950,7 @@ pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
             };
             let mut fcx = traits::FulfillmentContext::new_in_snapshot();
             fcx.register_predicate_obligations(self, ok.obligations);
-            fcx.select_where_possible(&self).is_ok()
+            fcx.select_where_possible(&self).is_empty()
         })
     }
 
index d5b631df058aef9c12428677dbfa52f7aec344d3..cbfd8747ecf0091b16c6c711ee9e83c4771d5c3e 100644 (file)
@@ -92,7 +92,6 @@ fn compare_predicate_entailment<'tcx>(
         impl_m_span,
         impl_m_hir_id,
         ObligationCauseCode::CompareImplMethodObligation {
-            item_name: impl_m.ident.name,
             impl_item_def_id: impl_m.def_id,
             trait_item_def_id: trait_m.def_id,
         },
@@ -391,8 +390,9 @@ fn compare_predicate_entailment<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
@@ -453,6 +453,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
     Ok(())
 }
 
+#[instrument(level = "debug", skip(infcx))]
 fn extract_spans_for_error_reporting<'a, 'tcx>(
     infcx: &infer::InferCtxt<'a, 'tcx>,
     terr: &TypeError<'_>,
@@ -1093,8 +1094,9 @@ fn compare_const_param_types<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return;
         }
 
@@ -1164,7 +1166,6 @@ fn compare_type_predicate_entailment<'tcx>(
         impl_ty_span,
         impl_ty_hir_id,
         ObligationCauseCode::CompareImplTypeObligation {
-            item_name: impl_ty.ident.name,
             impl_item_def_id: impl_ty.def_id,
             trait_item_def_id: trait_ty.def_id,
         },
@@ -1209,8 +1210,9 @@ fn compare_type_predicate_entailment<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
@@ -1426,10 +1428,10 @@ pub fn check_type_bounds<'tcx>(
 
         // Check that all obligations are satisfied by the implementation's
         // version.
-        if let Err(ref errors) =
-            inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
-        {
-            infcx.report_fulfillment_errors(errors, None, false);
+        let errors =
+            inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness);
+        if !errors.is_empty() {
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
index 2b3672211e4f582e951922e2ff2c555c4b36866f..9bbe52591472885655471958f9bf7632c42385b4 100644 (file)
@@ -29,6 +29,7 @@ pub fn emit_coerce_suggestions(
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) {
         self.annotate_expected_due_to_let_ty(err, expr);
+        self.suggest_box_deref(err, expr, expected, expr_ty);
         self.suggest_compatible_variants(err, expr, expected, expr_ty);
         self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
         if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
@@ -167,6 +168,23 @@ fn annotate_expected_due_to_let_ty(
         }
     }
 
+    fn suggest_box_deref(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr<'_>,
+        expected: Ty<'tcx>,
+        expr_ty: Ty<'tcx>,
+    ) {
+        if expr_ty.is_box() && expr_ty.boxed_ty() == expected {
+            err.span_suggestion_verbose(
+                expr.span.shrink_to_lo(),
+                "try dereferencing the `Box`",
+                "*".to_string(),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
     /// If the expected type is an enum (Issue #55250) with any variants whose
     /// sole field is of the found type, suggest such variants. (Issue #42764)
     fn suggest_compatible_variants(
@@ -428,7 +446,7 @@ pub fn check_ref(
                 (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => {
                     if let hir::ExprKind::Lit(_) = expr.kind {
                         if let Ok(src) = sm.span_to_snippet(sp) {
-                            if let Some(_) = replace_prefix(&src, "b\"", "\"") {
+                            if replace_prefix(&src, "b\"", "\"").is_some() {
                                 let pos = sp.lo() + BytePos(1);
                                 return Some((
                                     sp.with_hi(pos),
@@ -444,7 +462,7 @@ pub fn check_ref(
                 (&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => {
                     if let hir::ExprKind::Lit(_) = expr.kind {
                         if let Ok(src) = sm.span_to_snippet(sp) {
-                            if let Some(_) = replace_prefix(&src, "\"", "b\"") {
+                            if replace_prefix(&src, "\"", "b\"").is_some() {
                                 return Some((
                                     sp.shrink_to_lo(),
                                     "consider adding a leading `b`",
index fd150978f0074d8a5c4aea01e80090906b03221a..bfa0d92ab47ab9546bfde2ee8b4a42f886675343 100644 (file)
@@ -113,9 +113,10 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
             }
         }
 
-        if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
+        let errors = fulfillment_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
             // this could be reached when we get lazy normalization
-            infcx.report_fulfillment_errors(errors, None, false);
+            infcx.report_fulfillment_errors(&errors, None, false);
             return Err(ErrorReported);
         }
 
index 3846aad2cfc103e2447cb27de49bea72afb9a23d..5c79a067e9f047e74a66005f0365ed5620136d8a 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ExprKind, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_middle::ty;
+use rustc_infer::infer::InferOk;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
+use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts};
+use rustc_middle::ty::relate::expected_found_bool;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::Ty;
-use rustc_middle::ty::TypeFoldable;
-use rustc_middle::ty::{AdtKind, Visibility};
+use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable};
+use rustc_session::parse::feature_err;
 use rustc_span::edition::LATEST_STABLE_EDITION;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -323,7 +325,9 @@ fn check_expr_kind(
             }
             ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
             ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
-            ExprKind::ConstBlock(ref anon_const) => self.to_const(anon_const).ty,
+            ExprKind::ConstBlock(ref anon_const) => {
+                self.check_expr_const_block(anon_const, expected, expr)
+            }
             ExprKind::Repeat(element, ref count) => {
                 self.check_expr_repeat(element, count, expected, expr)
             }
@@ -1166,6 +1170,24 @@ fn check_expr_array(
         self.tcx.mk_array(element_ty, args.len() as u64)
     }
 
+    fn check_expr_const_block(
+        &self,
+        anon_const: &'tcx hir::AnonConst,
+        expected: Expectation<'tcx>,
+        _expr: &'tcx hir::Expr<'tcx>,
+    ) -> Ty<'tcx> {
+        let body = self.tcx.hir().body(anon_const.body);
+
+        // Create a new function context.
+        let fcx = FnCtxt::new(self, self.param_env, body.value.hir_id);
+        crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body);
+
+        let ty = fcx.check_expr_with_expectation(&body.value, expected);
+        fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized);
+        fcx.write_ty(anon_const.hir_id, ty);
+        ty
+    }
+
     fn check_expr_repeat(
         &self,
         element: &'tcx hir::Expr<'tcx>,
@@ -1262,49 +1284,17 @@ fn check_expr_struct(
                 .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() });
         }
 
-        let error_happened = self.check_expr_struct_fields(
+        self.check_expr_struct_fields(
             adt_ty,
             expected,
             expr.hir_id,
             qpath.span(),
             variant,
             fields,
-            base_expr.is_none(),
+            base_expr,
             expr.span,
         );
-        if let Some(base_expr) = base_expr {
-            // If check_expr_struct_fields hit an error, do not attempt to populate
-            // the fields with the base_expr. This could cause us to hit errors later
-            // when certain fields are assumed to exist that in fact do not.
-            if !error_happened {
-                self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {});
-                match adt_ty.kind() {
-                    ty::Adt(adt, substs) if adt.is_struct() => {
-                        let fru_field_types = adt
-                            .non_enum_variant()
-                            .fields
-                            .iter()
-                            .map(|f| {
-                                self.normalize_associated_types_in(
-                                    expr.span,
-                                    f.ty(self.tcx, substs),
-                                )
-                            })
-                            .collect();
-
-                        self.typeck_results
-                            .borrow_mut()
-                            .fru_field_types_mut()
-                            .insert(expr.hir_id, fru_field_types);
-                    }
-                    _ => {
-                        self.tcx
-                            .sess
-                            .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
-                    }
-                }
-            }
-        }
+
         self.require_type_is_sized(adt_ty, expr.span, traits::StructInitializerSized);
         adt_ty
     }
@@ -1317,9 +1307,9 @@ fn check_expr_struct_fields(
         span: Span,
         variant: &'tcx ty::VariantDef,
         ast_fields: &'tcx [hir::ExprField<'tcx>],
-        check_completeness: bool,
+        base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
         expr_span: Span,
-    ) -> bool {
+    ) {
         let tcx = self.tcx;
 
         let adt_ty_hint = self
@@ -1394,7 +1384,116 @@ fn check_expr_struct_fields(
                 )
                 .emit();
             }
-        } else if check_completeness && !error_happened && !remaining_fields.is_empty() {
+        }
+
+        // If check_expr_struct_fields hit an error, do not attempt to populate
+        // the fields with the base_expr. This could cause us to hit errors later
+        // when certain fields are assumed to exist that in fact do not.
+        if error_happened {
+            return;
+        }
+
+        if let Some(base_expr) = base_expr {
+            // FIXME: We are currently creating two branches here in order to maintain
+            // consistency. But they should be merged as much as possible.
+            let fru_tys = if self.tcx.features().type_changing_struct_update {
+                let base_ty = self.check_expr(base_expr);
+                match adt_ty.kind() {
+                    ty::Adt(adt, substs) if adt.is_struct() => {
+                        match base_ty.kind() {
+                            ty::Adt(base_adt, base_subs) if adt == base_adt => {
+                                variant
+                                    .fields
+                                    .iter()
+                                    .map(|f| {
+                                        let fru_ty = self.normalize_associated_types_in(
+                                            expr_span,
+                                            self.field_ty(base_expr.span, f, base_subs),
+                                        );
+                                        let ident = self.tcx.adjust_ident(f.ident, variant.def_id);
+                                        if let Some(_) = remaining_fields.remove(&ident) {
+                                            let target_ty =
+                                                self.field_ty(base_expr.span, f, substs);
+                                            let cause = self.misc(base_expr.span);
+                                            match self
+                                                .at(&cause, self.param_env)
+                                                .sup(target_ty, fru_ty)
+                                            {
+                                                Ok(InferOk { obligations, value: () }) => {
+                                                    self.register_predicates(obligations)
+                                                }
+                                                // FIXME: Need better diagnostics for `FieldMisMatch` error
+                                                Err(_) => self
+                                                    .report_mismatched_types(
+                                                        &cause,
+                                                        target_ty,
+                                                        fru_ty,
+                                                        FieldMisMatch(
+                                                            variant.ident.name,
+                                                            ident.name,
+                                                        ),
+                                                    )
+                                                    .emit(),
+                                            }
+                                        }
+                                        fru_ty
+                                    })
+                                    .collect()
+                            }
+                            _ => {
+                                return self
+                                    .report_mismatched_types(
+                                        &self.misc(base_expr.span),
+                                        adt_ty,
+                                        base_ty,
+                                        Sorts(expected_found_bool(true, adt_ty, base_ty)),
+                                    )
+                                    .emit();
+                            }
+                        }
+                    }
+                    _ => {
+                        return self
+                            .tcx
+                            .sess
+                            .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
+                    }
+                }
+            } else {
+                self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {
+                    let base_ty = self.check_expr(base_expr);
+                    let same_adt = match (adt_ty.kind(), base_ty.kind()) {
+                        (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt => true,
+                        _ => false,
+                    };
+                    if self.tcx.sess.is_nightly_build() && same_adt {
+                        feature_err(
+                            &self.tcx.sess.parse_sess,
+                            sym::type_changing_struct_update,
+                            base_expr.span,
+                            "type changing struct updating is experimental",
+                        )
+                        .emit();
+                    }
+                });
+                match adt_ty.kind() {
+                    ty::Adt(adt, substs) if adt.is_struct() => variant
+                        .fields
+                        .iter()
+                        .map(|f| {
+                            self.normalize_associated_types_in(expr_span, f.ty(self.tcx, substs))
+                        })
+                        .collect(),
+                    _ => {
+                        return self
+                            .tcx
+                            .sess
+                            .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
+                    }
+                }
+            };
+            self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys);
+        } else if kind_name != "union" && !remaining_fields.is_empty() {
             let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| {
                 !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
             });
@@ -1405,8 +1504,6 @@ fn check_expr_struct_fields(
                 self.report_missing_fields(adt_ty, span, remaining_fields);
             }
         }
-
-        error_happened
     }
 
     fn check_struct_fields_on_error(
@@ -1632,7 +1729,7 @@ fn suggest_field_name(
             .filter_map(|field| {
                 // ignore already set fields and private fields from non-local crates
                 if skip.iter().any(|&x| x == field.ident.name)
-                    || (!variant.def_id.is_local() && field.vis != Visibility::Public)
+                    || (!variant.def_id.is_local() && !field.vis.is_public())
                 {
                     None
                 } else {
@@ -1698,15 +1795,15 @@ fn check_field(
                         // Save the index of all fields regardless of their visibility in case
                         // of error recovery.
                         self.write_field_index(expr.hir_id, index);
+                        let adjustments = self.adjust_steps(&autoderef);
                         if field.vis.is_accessible_from(def_scope, self.tcx) {
-                            let adjustments = self.adjust_steps(&autoderef);
                             self.apply_adjustments(base, adjustments);
                             self.register_predicates(autoderef.into_obligations());
 
                             self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
                             return field_ty;
                         }
-                        private_candidate = Some((base_def.did, field_ty));
+                        private_candidate = Some((adjustments, base_def.did, field_ty));
                     }
                 }
                 ty::Tuple(tys) => {
@@ -1729,7 +1826,10 @@ fn check_field(
         }
         self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
 
-        if let Some((did, field_ty)) = private_candidate {
+        if let Some((adjustments, did, field_ty)) = private_candidate {
+            // (#90483) apply adjustments to avoid ExprUseVisitor from
+            // creating erroneous projection.
+            self.apply_adjustments(base, adjustments);
             self.ban_private_field_access(expr, expr_t, field, did);
             return field_ty;
         }
@@ -2055,8 +2155,7 @@ fn get_field_candidates(
     ) -> Option<(&Vec<ty::FieldDef>, SubstsRef<'tcx>)> {
         debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_t);
 
-        let mut autoderef = self.autoderef(span, base_t);
-        while let Some((base_t, _)) = autoderef.next() {
+        for (base_t, _) in self.autoderef(span, base_t) {
             match base_t.kind() {
                 ty::Adt(base_def, substs) if !base_def.is_enum() => {
                     let fields = &base_def.non_enum_variant().fields;
index 296e45337ed1035b3ed1868396f371ba6b045c86..e5da33d113e7c48e95ab6e626d4e0dc8ff0711f8 100644 (file)
@@ -176,7 +176,7 @@ fn fallback_opaque_type_vars(&self, ty: Ty<'tcx>) -> bool {
             .type_var_origin(ty)
             .map(|origin| origin.span)
             .unwrap_or(rustc_span::DUMMY_SP);
-        let oty = self.inner.borrow().opaque_types_vars.get(ty).map(|v| *v);
+        let oty = self.inner.borrow().opaque_types_vars.get(ty).copied();
         if let Some(opaque_ty) = oty {
             debug!(
                 "fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}",
index 5308126f2524b2468078d0c6e1db96efebd86506..93b2a595259722923447a3a5de4bbdc192c8f498 100644 (file)
@@ -642,11 +642,12 @@ pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
 
     #[instrument(skip(self), level = "debug")]
     pub(in super::super) fn select_all_obligations_or_error(&self) {
-        if let Err(errors) = self
+        let errors = self
             .fulfillment_cx
             .borrow_mut()
-            .select_all_with_constness_or_error(&self, self.inh.constness)
-        {
+            .select_all_with_constness_or_error(&self, self.inh.constness);
+
+        if !errors.is_empty() {
             self.report_fulfillment_errors(&errors, self.inh.body_id, false);
         }
     }
@@ -657,13 +658,13 @@ pub(in super::super) fn select_obligations_where_possible(
         fallback_has_occurred: bool,
         mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
     ) {
-        let result = self
+        let mut result = self
             .fulfillment_cx
             .borrow_mut()
             .select_with_constness_where_possible(self, self.inh.constness);
-        if let Err(mut errors) = result {
-            mutate_fulfillment_errors(&mut errors);
-            self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred);
+        if !result.is_empty() {
+            mutate_fulfillment_errors(&mut result);
+            self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
         }
     }
 
@@ -793,14 +794,17 @@ pub(in super::super) fn expected_inputs_for_expected_output(
                         // we can.  We don't care if some things turn
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
-                        self.save_and_restore_in_snapshot_flag(|_| {
+                        let errors = self.save_and_restore_in_snapshot_flag(|_| {
                             let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
                             for obligation in ok.obligations {
                                 fulfill.register_predicate_obligation(self, obligation);
                             }
                             fulfill.select_where_possible(self)
-                        })
-                        .map_err(|_| ())?;
+                        });
+
+                        if !errors.is_empty() {
+                            return Err(());
+                        }
                     }
                     Err(_) => return Err(()),
                 }
index b3e18dab363692e303e13e4977355579d1967c68..7d9483201f6a547c5e3ae407e473a8ad19f7e729 100644 (file)
@@ -1045,34 +1045,32 @@ fn point_at_type_arg_instead_of_call_if_possible(
         call_expr: &'tcx hir::Expr<'tcx>,
     ) {
         if let hir::ExprKind::Call(path, _) = &call_expr.kind {
-            if let hir::ExprKind::Path(qpath) = &path.kind {
-                if let hir::QPath::Resolved(_, path) = &qpath {
-                    for error in errors {
-                        if let ty::PredicateKind::Trait(predicate) =
-                            error.obligation.predicate.kind().skip_binder()
+            if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
+                for error in errors {
+                    if let ty::PredicateKind::Trait(predicate) =
+                        error.obligation.predicate.kind().skip_binder()
+                    {
+                        // If any of the type arguments in this path segment caused the
+                        // `FulfillmentError`, point at its span (#61860).
+                        for arg in path
+                            .segments
+                            .iter()
+                            .filter_map(|seg| seg.args.as_ref())
+                            .flat_map(|a| a.args.iter())
                         {
-                            // If any of the type arguments in this path segment caused the
-                            // `FulfillmentError`, point at its span (#61860).
-                            for arg in path
-                                .segments
-                                .iter()
-                                .filter_map(|seg| seg.args.as_ref())
-                                .flat_map(|a| a.args.iter())
-                            {
-                                if let hir::GenericArg::Type(hir_ty) = &arg {
-                                    if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
-                                        &hir_ty.kind
-                                    {
-                                        // Avoid ICE with associated types. As this is best
-                                        // effort only, it's ok to ignore the case. It
-                                        // would trigger in `is_send::<T::AssocType>();`
-                                        // from `typeck-default-trait-impl-assoc-type.rs`.
-                                    } else {
-                                        let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
-                                        let ty = self.resolve_vars_if_possible(ty);
-                                        if ty == predicate.self_ty() {
-                                            error.obligation.cause.make_mut().span = hir_ty.span;
-                                        }
+                            if let hir::GenericArg::Type(hir_ty) = &arg {
+                                if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
+                                    &hir_ty.kind
+                                {
+                                    // Avoid ICE with associated types. As this is best
+                                    // effort only, it's ok to ignore the case. It
+                                    // would trigger in `is_send::<T::AssocType>();`
+                                    // from `typeck-default-trait-impl-assoc-type.rs`.
+                                } else {
+                                    let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
+                                    let ty = self.resolve_vars_if_possible(ty);
+                                    if ty == predicate.self_ty() {
+                                        error.obligation.cause.make_mut().span = hir_ty.span;
                                     }
                                 }
                             }
index 8007b9f23776a169f141afa3d63ca7f61617839a..71cd8a43329c5df8a8f25bdab7c2d310fb3a1158 100644 (file)
@@ -1208,7 +1208,7 @@ fn suggest_valid_traits(
             let edition_fix = candidates
                 .iter()
                 .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
-                .map(|&d| d);
+                .copied();
 
             err.help("items from traits can only be used if the trait is in scope");
             let msg = format!(
@@ -1410,7 +1410,7 @@ fn suggest_traits_to_import(
                                 }
                             }
                             // We only want to suggest public or local traits (#45781).
-                            item.vis == ty::Visibility::Public || info.def_id.is_local()
+                            item.vis.is_public() || info.def_id.is_local()
                         })
                         .is_some()
             })
index 7450b4a4ef1c3f23c0f1554a044f9c6b708df1b4..d19e99606bcd8eec3f0d54d7e921de2ec1e463a9 100644 (file)
@@ -297,9 +297,9 @@ fn primary_body_of(
 fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
-    let outer_def_id = tcx.closure_base_def_id(def_id);
-    if outer_def_id != def_id {
-        return tcx.has_typeck_results(outer_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+    if typeck_root_def_id != def_id {
+        return tcx.has_typeck_results(typeck_root_def_id);
     }
 
     if let Some(def_id) = def_id.as_local() {
@@ -348,9 +348,9 @@ fn typeck_with_fallback<'tcx>(
 ) -> &'tcx ty::TypeckResults<'tcx> {
     // Closures' typeck results come from their outermost function,
     // as they are part of the same "inference environment".
-    let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
-    if outer_def_id != def_id {
-        return tcx.typeck(outer_def_id);
+    let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
+    if typeck_root_def_id != def_id {
+        return tcx.typeck(typeck_root_def_id);
     }
 
     let id = tcx.hir().local_def_id_to_hir_id(def_id);
index aea1bcd95df21a63504981b9e25075a54882d89f..9c53a1d4eb68dacc98fba193e2e9efb3963d9f88 100644 (file)
@@ -399,12 +399,9 @@ fn check_overloaded_binop(
                     }
                 };
                 if let Ref(_, rty, _) = lhs_ty.kind() {
-                    if {
-                        self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span)
-                            && self
-                                .lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign))
-                                .is_ok()
-                    } {
+                    if self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span)
+                        && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)).is_ok()
+                    {
                         if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
                             let msg = &format!(
                                 "`{}{}` can be used on `{}`, you can dereference `{}`",
@@ -829,10 +826,7 @@ fn lookup_op_method(
                     self.obligation_for_method(span, trait_did, lhs_ty, Some(other_tys));
                 let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
                 fulfill.register_predicate_obligation(self, obligation);
-                Err(match fulfill.select_where_possible(&self.infcx) {
-                    Err(errors) => errors,
-                    _ => vec![],
-                })
+                Err(fulfill.select_where_possible(&self.infcx))
             }
         }
     }
index 5aa11cce25fb6d5247d38f9757f3bea37c5d6487..cbf33cf1b78a147112c2ad55cd868a845a813eb3 100644 (file)
@@ -292,7 +292,9 @@ fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option<Res>) -> A
             // String and byte-string literals result in types `&str` and `&[u8]` respectively.
             // All other literals result in non-reference types.
             // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`.
-            PatKind::Lit(lt) => match self.check_expr(lt).kind() {
+            //
+            // Call `resolve_vars_if_possible` here for inline const blocks.
+            PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
                 ty::Ref(..) => AdjustMode::Pass,
                 _ => AdjustMode::Peel,
             },
index 86d4e4d2b115b5857959bd115066bc850a5a8543..d2d8b14dd9695e917bd27d2dc4a08d7683993991 100644 (file)
@@ -341,6 +341,29 @@ fn visit_fn_body(
         self.visit_region_obligations(body_id.hir_id);
     }
 
+    fn visit_inline_const(&mut self, id: hir::HirId, body: &'tcx hir::Body<'tcx>) {
+        debug!("visit_inline_const(id={:?})", id);
+
+        // Save state of current function. We will restore afterwards.
+        let old_body_id = self.body_id;
+        let old_body_owner = self.body_owner;
+        let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child();
+
+        let body_id = body.id();
+        self.body_id = body_id.hir_id;
+        self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
+
+        self.outlives_environment.save_implied_bounds(body_id.hir_id);
+
+        self.visit_body(body);
+        self.visit_region_obligations(body_id.hir_id);
+
+        // Restore state from previous function.
+        self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot);
+        self.body_id = old_body_id;
+        self.body_owner = old_body_owner;
+    }
+
     fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
         debug!("visit_region_obligations: hir_id={:?}", hir_id);
 
@@ -406,13 +429,13 @@ fn visit_fn(
         // `visit_fn_body`.  We will restore afterwards.
         let old_body_id = self.body_id;
         let old_body_owner = self.body_owner;
-        let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
+        let env_snapshot = self.outlives_environment.push_snapshot_pre_typeck_child();
 
         let body = self.tcx.hir().body(body_id);
         self.visit_fn_body(hir_id, body, span);
 
         // Restore state from previous function.
-        self.outlives_environment.pop_snapshot_post_closure(env_snapshot);
+        self.outlives_environment.pop_snapshot_post_typeck_child(env_snapshot);
         self.body_id = old_body_id;
         self.body_owner = old_body_owner;
     }
@@ -460,6 +483,11 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                 intravisit::walk_expr(self, expr);
             }
 
+            hir::ExprKind::ConstBlock(anon_const) => {
+                let body = self.tcx.hir().body(anon_const.body);
+                self.visit_inline_const(anon_const.hir_id, body);
+            }
+
             _ => intravisit::walk_expr(self, expr),
         }
     }
index 774d8078e52ca31171213b8070848902040aae07..5f5d308a3329bdf5c7f3c3fe2cbd1e0a445c4f8c 100644 (file)
@@ -148,10 +148,17 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-        if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.kind {
-            let body = self.fcx.tcx.hir().body(body_id);
-            self.visit_body(body);
-            self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
+        match expr.kind {
+            hir::ExprKind::Closure(cc, _, body_id, _, _) => {
+                let body = self.fcx.tcx.hir().body(body_id);
+                self.visit_body(body);
+                self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, cc);
+            }
+            hir::ExprKind::ConstBlock(anon_const) => {
+                let body = self.fcx.tcx.hir().body(anon_const.body);
+                self.visit_body(body);
+            }
+            _ => {}
         }
 
         intravisit::walk_expr(self, expr);
index 06bfc427bbabcf45a912e802e11f109a40122ea1..c1adc2894ccfcd365541de28932c886fb71ae4f5 100644 (file)
@@ -435,9 +435,7 @@ fn check_gat_where_clauses(
         let written_predicates: ty::GenericPredicates<'_> =
             tcx.explicit_predicates_of(trait_item.def_id);
         let mut clauses: Vec<_> = clauses
-            .drain_filter(|clause| {
-                written_predicates.predicates.iter().find(|p| &p.0 == clause).is_none()
-            })
+            .drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause))
             .map(|clause| format!("{}", clause))
             .collect();
         // We sort so that order is predictable
index d951df94dcf50fbb0a2d137feb5ebf182843a782..fdc8b6b5e64519d57642ad6549ec858d880fcc89 100644 (file)
@@ -282,6 +282,12 @@ fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
             hir::ExprKind::Field(..) => {
                 self.visit_field_id(e.hir_id);
             }
+            hir::ExprKind::ConstBlock(anon_const) => {
+                self.visit_node_id(e.span, anon_const.hir_id);
+
+                let body = self.tcx().hir().body(anon_const.body);
+                self.visit_body(body);
+            }
             _ => {}
         }
 
index 8cae61e8c22f6ffd3708e706de6fbd333d15f96e..372e83592b9c51335fcc04e529071d6684c5b06a 100644 (file)
@@ -180,14 +180,14 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
 
                 let coerced_fields = fields
                     .iter()
-                    .filter_map(|field| {
+                    .filter(|field| {
                         let ty_a = field.ty(tcx, substs_a);
                         let ty_b = field.ty(tcx, substs_b);
 
                         if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
                             if layout.is_zst() && layout.align.abi.bytes() == 1 {
                                 // ignore ZST fields with alignment of 1 byte
-                                return None;
+                                return false;
                             }
                         }
 
@@ -204,11 +204,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                                 ))
                                 .emit();
 
-                                return None;
+                                return false;
                             }
                         }
 
-                        Some(field)
+                        return true;
                     })
                     .collect::<Vec<_>>();
 
@@ -263,7 +263,8 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
                     }
 
                     // Check that all transitive obligations are satisfied.
-                    if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+                    let errors = fulfill_cx.select_all_or_error(&infcx);
+                    if !errors.is_empty() {
                         infcx.report_fulfillment_errors(&errors, None, false);
                     }
 
@@ -522,7 +523,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
         fulfill_cx.register_predicate_obligation(&infcx, predicate);
 
         // Check that all transitive obligations are satisfied.
-        if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+        let errors = fulfill_cx.select_all_or_error(&infcx);
+        if !errors.is_empty() {
             infcx.report_fulfillment_errors(&errors, None, false);
         }
 
index 079604f128d433812e2a389dca16e34f0f4342de..377ebf1fe2a9f5fdad1b5a23e4ebc4492182d594 100644 (file)
@@ -168,6 +168,7 @@ pub fn provide(providers: &mut Providers) {
     use self::builtin::coerce_unsized_info;
     use self::inherent_impls::{crate_inherent_impls, inherent_impls};
     use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
+    use self::orphan::orphan_check_crate;
 
     *providers = Providers {
         coherent_trait,
@@ -175,6 +176,7 @@ pub fn provide(providers: &mut Providers) {
         inherent_impls,
         crate_inherent_impls_overlap_check,
         coerce_unsized_info,
+        orphan_check_crate,
         ..*providers
     };
 }
@@ -195,13 +197,13 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
 }
 
 pub fn check_coherence(tcx: TyCtxt<'_>) {
+    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
+    tcx.ensure().orphan_check_crate(());
+
     for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
         tcx.ensure().coherent_trait(trait_def_id);
     }
 
-    tcx.sess.time("unsafety_checking", || unsafety::check(tcx));
-    tcx.sess.time("orphan_checking", || orphan::check(tcx));
-
     // these queries are executed for side-effects (error reporting):
     tcx.ensure().crate_inherent_impls(());
     tcx.ensure().crate_inherent_impls_overlap_check(());
index 0326d1fd74f62c0548718e1a5033b28d3d5f3652..b450d3f6c08ab98b04f1d622855b9ed10de1ffda 100644 (file)
 //! crate or pertains to a type defined in this crate.
 
 use rustc_errors::struct_span_err;
+use rustc_errors::ErrorReported;
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::Span;
 use rustc_trait_selection::traits;
 
-pub fn check(tcx: TyCtxt<'_>) {
-    let mut orphan = OrphanChecker { tcx };
-    tcx.hir().visit_all_item_likes(&mut orphan);
+pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] {
+    let mut errors = Vec::new();
+    for (_trait, impls_of_trait) in tcx.all_local_trait_impls(()) {
+        for &impl_of_trait in impls_of_trait {
+            match orphan_check_impl(tcx, impl_of_trait) {
+                Ok(()) => {}
+                Err(ErrorReported) => errors.push(impl_of_trait),
+            }
+        }
+    }
+    tcx.arena.alloc_slice(&errors)
 }
 
-struct OrphanChecker<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
+#[instrument(skip(tcx), level = "debug")]
+fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorReported> {
+    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
+    let trait_def_id = trait_ref.def_id;
 
-impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
-    /// Checks exactly one impl for orphan rules and other such
-    /// restrictions. In this fn, it can happen that multiple errors
-    /// apply to a specific impl, so just return after reporting one
-    /// to prevent inundating the user with a bunch of similar error
-    /// reports.
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        // "Trait" impl
-        if let hir::ItemKind::Impl(hir::Impl {
-            generics, of_trait: Some(ref tr), self_ty, ..
-        }) = &item.kind
-        {
-            debug!(
-                "coherence2::orphan check: trait impl {}",
-                self.tcx.hir().node_to_string(item.hir_id())
-            );
-            let trait_ref = self.tcx.impl_trait_ref(item.def_id).unwrap();
-            let trait_def_id = trait_ref.def_id;
-            let sm = self.tcx.sess.source_map();
-            let sp = sm.guess_head_span(item.span);
-            match traits::orphan_check(self.tcx, item.def_id.to_def_id()) {
-                Ok(()) => {}
-                Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => {
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        sp,
-                        E0117,
-                        "only traits defined in the current crate can be implemented for \
-                         arbitrary types"
-                    );
-                    err.span_label(sp, "impl doesn't use only types from inside the current crate");
-                    for (ty, is_target_ty) in &tys {
-                        let mut ty = *ty;
-                        self.tcx.infer_ctxt().enter(|infcx| {
-                            // Remove the lifetimes unnecessary for this error.
-                            ty = infcx.freshen(ty);
-                        });
-                        ty = match ty.kind() {
-                            // Remove the type arguments from the output, as they are not relevant.
-                            // You can think of this as the reverse of `resolve_vars_if_possible`.
-                            // That way if we had `Vec<MyType>`, we will properly attribute the
-                            // problem to `Vec<T>` and avoid confusing the user if they were to see
-                            // `MyType` in the error.
-                            ty::Adt(def, _) => self.tcx.mk_adt(def, ty::List::empty()),
-                            _ => ty,
-                        };
-                        let this = "this".to_string();
-                        let (ty, postfix) = match &ty.kind() {
-                            ty::Slice(_) => (this, " because slices are always foreign"),
-                            ty::Array(..) => (this, " because arrays are always foreign"),
-                            ty::Tuple(..) => (this, " because tuples are always foreign"),
-                            _ => (format!("`{}`", ty), ""),
-                        };
-                        let msg = format!("{} is not defined in the current crate{}", ty, postfix);
-                        if *is_target_ty {
-                            // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
-                            err.span_label(self_ty.span, &msg);
-                        } else {
-                            // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
-                            err.span_label(tr.path.span, &msg);
-                        }
-                    }
-                    err.note("define and implement a trait or new type instead");
-                    err.emit();
-                    return;
-                }
-                Err(traits::OrphanCheckErr::UncoveredTy(param_ty, local_type)) => {
-                    let mut sp = sp;
-                    for param in generics.params {
-                        if param.name.ident().to_string() == param_ty.to_string() {
-                            sp = param.span;
-                        }
-                    }
+    let item = tcx.hir().item(hir::ItemId { def_id });
+    let impl_ = match item.kind {
+        hir::ItemKind::Impl(ref impl_) => impl_,
+        _ => bug!("{:?} is not an impl: {:?}", def_id, item),
+    };
+    let sp = tcx.sess.source_map().guess_head_span(item.span);
+    let tr = impl_.of_trait.as_ref().unwrap();
+    match traits::orphan_check(tcx, item.def_id.to_def_id()) {
+        Ok(()) => {}
+        Err(err) => emit_orphan_check_error(
+            tcx,
+            sp,
+            tr.path.span,
+            impl_.self_ty.span,
+            &impl_.generics,
+            err,
+        )?,
+    }
+
+    // In addition to the above rules, we restrict impls of auto traits
+    // so that they can only be implemented on nominal types, such as structs,
+    // enums or foreign types. To see why this restriction exists, consider the
+    // following example (#22978). Imagine that crate A defines an auto trait
+    // `Foo` and a fn that operates on pairs of types:
+    //
+    // ```
+    // // Crate A
+    // auto trait Foo { }
+    // fn two_foos<A:Foo,B:Foo>(..) {
+    //     one_foo::<(A,B)>(..)
+    // }
+    // fn one_foo<T:Foo>(..) { .. }
+    // ```
+    //
+    // This type-checks fine; in particular the fn
+    // `two_foos` is able to conclude that `(A,B):Foo`
+    // because `A:Foo` and `B:Foo`.
+    //
+    // Now imagine that crate B comes along and does the following:
+    //
+    // ```
+    // struct A { }
+    // struct B { }
+    // impl Foo for A { }
+    // impl Foo for B { }
+    // impl !Send for (A, B) { }
+    // ```
+    //
+    // This final impl is legal according to the orphan
+    // rules, but it invalidates the reasoning from
+    // `two_foos` above.
+    debug!(
+        "trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
+        trait_ref,
+        trait_def_id,
+        tcx.trait_is_auto(trait_def_id)
+    );
+
+    if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
+        let self_ty = trait_ref.self_ty();
+        let opt_self_def_id = match *self_ty.kind() {
+            ty::Adt(self_def, _) => Some(self_def.did),
+            ty::Foreign(did) => Some(did),
+            _ => None,
+        };
 
-                    match local_type {
-                        Some(local_type) => {
-                            struct_span_err!(
-                                self.tcx.sess,
-                                sp,
-                                E0210,
-                                "type parameter `{}` must be covered by another type \
-                                when it appears before the first local type (`{}`)",
-                                param_ty,
-                                local_type
-                            )
-                            .span_label(
-                                sp,
-                                format!(
-                                    "type parameter `{}` must be covered by another type \
-                                when it appears before the first local type (`{}`)",
-                                    param_ty, local_type
-                                ),
-                            )
-                            .note(
-                                "implementing a foreign trait is only possible if at \
-                                    least one of the types for which it is implemented is local, \
-                                    and no uncovered type parameters appear before that first \
-                                    local type",
-                            )
-                            .note(
-                                "in this case, 'before' refers to the following order: \
-                                    `impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
-                                    where `T0` is the first and `Tn` is the last",
-                            )
-                            .emit();
-                        }
-                        None => {
-                            struct_span_err!(
-                                self.tcx.sess,
-                                sp,
-                                E0210,
-                                "type parameter `{}` must be used as the type parameter for some \
-                                local type (e.g., `MyStruct<{}>`)",
-                                param_ty,
-                                param_ty
-                            ).span_label(sp, format!(
-                                "type parameter `{}` must be used as the type parameter for some \
-                                local type",
-                                param_ty,
-                            )).note("implementing a foreign trait is only possible if at \
-                                    least one of the types for which it is implemented is local"
-                            ).note("only traits defined in the current crate can be \
-                                    implemented for a type parameter"
-                            ).emit();
-                        }
-                    };
-                    return;
+        let msg = match opt_self_def_id {
+            // We only want to permit nominal types, but not *all* nominal types.
+            // They must be local to the current crate, so that people
+            // can't do `unsafe impl Send for Rc<SomethingLocal>` or
+            // `impl !Send for Box<SomethingLocalAndSend>`.
+            Some(self_def_id) => {
+                if self_def_id.is_local() {
+                    None
+                } else {
+                    Some((
+                        format!(
+                            "cross-crate traits with a default impl, like `{}`, \
+                                    can only be implemented for a struct/enum type \
+                                    defined in the current crate",
+                            tcx.def_path_str(trait_def_id)
+                        ),
+                        "can't implement cross-crate trait for type in another crate",
+                    ))
                 }
             }
+            _ => Some((
+                format!(
+                    "cross-crate traits with a default impl, like `{}`, can \
+                                only be implemented for a struct/enum type, not `{}`",
+                    tcx.def_path_str(trait_def_id),
+                    self_ty
+                ),
+                "can't implement cross-crate trait with a default impl for \
+                        non-struct/enum type",
+            )),
+        };
 
-            // In addition to the above rules, we restrict impls of auto traits
-            // so that they can only be implemented on nominal types, such as structs,
-            // enums or foreign types. To see why this restriction exists, consider the
-            // following example (#22978). Imagine that crate A defines an auto trait
-            // `Foo` and a fn that operates on pairs of types:
-            //
-            // ```
-            // // Crate A
-            // auto trait Foo { }
-            // fn two_foos<A:Foo,B:Foo>(..) {
-            //     one_foo::<(A,B)>(..)
-            // }
-            // fn one_foo<T:Foo>(..) { .. }
-            // ```
-            //
-            // This type-checks fine; in particular the fn
-            // `two_foos` is able to conclude that `(A,B):Foo`
-            // because `A:Foo` and `B:Foo`.
-            //
-            // Now imagine that crate B comes along and does the following:
-            //
-            // ```
-            // struct A { }
-            // struct B { }
-            // impl Foo for A { }
-            // impl Foo for B { }
-            // impl !Send for (A, B) { }
-            // ```
-            //
-            // This final impl is legal according to the orphan
-            // rules, but it invalidates the reasoning from
-            // `two_foos` above.
-            debug!(
-                "trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
-                trait_ref,
-                trait_def_id,
-                self.tcx.trait_is_auto(trait_def_id)
+        if let Some((msg, label)) = msg {
+            struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
+            return Err(ErrorReported);
+        }
+    }
+
+    if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
+        tcx.sess
+            .struct_span_err(sp, "cannot implement trait on type alias impl trait")
+            .span_note(tcx.def_span(def_id), "type alias impl trait defined here")
+            .emit();
+        return Err(ErrorReported);
+    }
+
+    Ok(())
+}
+
+fn emit_orphan_check_error(
+    tcx: TyCtxt<'tcx>,
+    sp: Span,
+    trait_span: Span,
+    self_ty_span: Span,
+    generics: &hir::Generics<'tcx>,
+    err: traits::OrphanCheckErr<'tcx>,
+) -> Result<!, ErrorReported> {
+    match err {
+        traits::OrphanCheckErr::NonLocalInputType(tys) => {
+            let mut err = struct_span_err!(
+                tcx.sess,
+                sp,
+                E0117,
+                "only traits defined in the current crate can be implemented for \
+                        arbitrary types"
             );
-            if self.tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
-                let self_ty = trait_ref.self_ty();
-                let opt_self_def_id = match *self_ty.kind() {
-                    ty::Adt(self_def, _) => Some(self_def.did),
-                    ty::Foreign(did) => Some(did),
-                    _ => None,
+            err.span_label(sp, "impl doesn't use only types from inside the current crate");
+            for (ty, is_target_ty) in &tys {
+                let mut ty = *ty;
+                tcx.infer_ctxt().enter(|infcx| {
+                    // Remove the lifetimes unnecessary for this error.
+                    ty = infcx.freshen(ty);
+                });
+                ty = match ty.kind() {
+                    // Remove the type arguments from the output, as they are not relevant.
+                    // You can think of this as the reverse of `resolve_vars_if_possible`.
+                    // That way if we had `Vec<MyType>`, we will properly attribute the
+                    // problem to `Vec<T>` and avoid confusing the user if they were to see
+                    // `MyType` in the error.
+                    ty::Adt(def, _) => tcx.mk_adt(def, ty::List::empty()),
+                    _ => ty,
                 };
-
-                let msg = match opt_self_def_id {
-                    // We only want to permit nominal types, but not *all* nominal types.
-                    // They must be local to the current crate, so that people
-                    // can't do `unsafe impl Send for Rc<SomethingLocal>` or
-                    // `impl !Send for Box<SomethingLocalAndSend>`.
-                    Some(self_def_id) => {
-                        if self_def_id.is_local() {
-                            None
-                        } else {
-                            Some((
-                                format!(
-                                    "cross-crate traits with a default impl, like `{}`, \
-                                         can only be implemented for a struct/enum type \
-                                         defined in the current crate",
-                                    self.tcx.def_path_str(trait_def_id)
-                                ),
-                                "can't implement cross-crate trait for type in another crate",
-                            ))
-                        }
-                    }
-                    _ => Some((
-                        format!(
-                            "cross-crate traits with a default impl, like `{}`, can \
-                                       only be implemented for a struct/enum type, not `{}`",
-                            self.tcx.def_path_str(trait_def_id),
-                            self_ty
-                        ),
-                        "can't implement cross-crate trait with a default impl for \
-                               non-struct/enum type",
-                    )),
+                let this = "this".to_string();
+                let (ty, postfix) = match &ty.kind() {
+                    ty::Slice(_) => (this, " because slices are always foreign"),
+                    ty::Array(..) => (this, " because arrays are always foreign"),
+                    ty::Tuple(..) => (this, " because tuples are always foreign"),
+                    _ => (format!("`{}`", ty), ""),
                 };
-
-                if let Some((msg, label)) = msg {
-                    struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
-                        .span_label(sp, label)
-                        .emit();
-                    return;
+                let msg = format!("{} is not defined in the current crate{}", ty, postfix);
+                if *is_target_ty {
+                    // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
+                    err.span_label(self_ty_span, &msg);
+                } else {
+                    // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
+                    err.span_label(trait_span, &msg);
+                }
+            }
+            err.note("define and implement a trait or new type instead");
+            err.emit()
+        }
+        traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => {
+            let mut sp = sp;
+            for param in generics.params {
+                if param.name.ident().to_string() == param_ty.to_string() {
+                    sp = param.span;
                 }
             }
 
-            if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
-                self.tcx
-                    .sess
-                    .struct_span_err(sp, "cannot implement trait on type alias impl trait")
-                    .span_note(self.tcx.def_span(def_id), "type alias impl trait defined here")
-                    .emit();
+            match local_type {
+                Some(local_type) => struct_span_err!(
+                    tcx.sess,
+                    sp,
+                    E0210,
+                    "type parameter `{}` must be covered by another type \
+                    when it appears before the first local type (`{}`)",
+                    param_ty,
+                    local_type
+                )
+                .span_label(
+                    sp,
+                    format!(
+                        "type parameter `{}` must be covered by another type \
+                    when it appears before the first local type (`{}`)",
+                        param_ty, local_type
+                    ),
+                )
+                .note(
+                    "implementing a foreign trait is only possible if at \
+                        least one of the types for which it is implemented is local, \
+                        and no uncovered type parameters appear before that first \
+                        local type",
+                )
+                .note(
+                    "in this case, 'before' refers to the following order: \
+                        `impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
+                        where `T0` is the first and `Tn` is the last",
+                )
+                .emit(),
+                None => struct_span_err!(
+                    tcx.sess,
+                    sp,
+                    E0210,
+                    "type parameter `{}` must be used as the type parameter for some \
+                    local type (e.g., `MyStruct<{}>`)",
+                    param_ty,
+                    param_ty
+                )
+                .span_label(
+                    sp,
+                    format!(
+                        "type parameter `{}` must be used as the type parameter for some \
+                    local type",
+                        param_ty,
+                    ),
+                )
+                .note(
+                    "implementing a foreign trait is only possible if at \
+                        least one of the types for which it is implemented is local",
+                )
+                .note(
+                    "only traits defined in the current crate can be \
+                        implemented for a type parameter",
+                )
+                .emit(),
             }
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
+    Err(ErrorReported)
 }
index 18e8ed394e81409615a9de263fd05626cb46cac5..2274db76c05fb264be490cb2043398dbf23e575c 100644 (file)
@@ -1494,13 +1494,15 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                     {
                         Some(parent_def_id.to_def_id())
                     }
-
+                    Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
+                        Some(tcx.typeck_root_def_id(def_id))
+                    }
                     _ => None,
                 }
             }
         }
         Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
-            Some(tcx.closure_base_def_id(def_id))
+            Some(tcx.typeck_root_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
             ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
@@ -1692,6 +1694,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
         }));
     }
 
+    // provide junk type parameter defs for const blocks.
+    if let Node::AnonConst(_) = node {
+        let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+        if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
+            params.push(ty::GenericParamDef {
+                index: type_start,
+                name: Symbol::intern("<const_ty>"),
+                def_id,
+                pure_wrt_drop: false,
+                kind: ty::GenericParamDefKind::Type {
+                    has_default: false,
+                    object_lifetime_default: rl::Set1::Empty,
+                    synthetic: None,
+                },
+            });
+        }
+    }
+
     let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
 
     ty::Generics {
index a6ea8abdf3fa6af554918f4a4aeceb51101a1d9d..04a68250ced0cd0a44387b6fa7d3abf868b03351 100644 (file)
@@ -494,7 +494,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
                     if anon_const.hir_id == hir_id =>
                 {
-                    tcx.typeck(def_id).node_type(anon_const.hir_id)
+                    let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+                    substs.as_inline_const().ty()
                 }
 
                 Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
index 39bcf8999323d7fb7a9a877cda60ee0d4b355bdb..a49eda6572de2cb3cf3248d6a5e317a3ab8ee893 100644 (file)
@@ -88,7 +88,8 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                     ),
                 );
 
-                if let Err(errors) = fulfill.select_all_or_error(&infcx) {
+                let errors = fulfill.select_all_or_error(&infcx);
+                if !errors.is_empty() {
                     tracing::debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
                     for error in errors {
                         if error.obligation.predicate == self.predicate {
index f90cfb8849160055ab7fce45bd5f7ddfd4867123..ba0fd12a2755f480568093ea79f6ee7acde5c994 100644 (file)
@@ -157,10 +157,10 @@ fn require_same_types<'tcx>(
             }
         }
 
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => true,
-            Err(errors) => {
-                infcx.report_fulfillment_errors(&errors, None, false);
+        match fulfill_cx.select_all_or_error(infcx).as_slice() {
+            [] => true,
+            errors => {
+                infcx.report_fulfillment_errors(errors, None, false);
                 false
             }
         }
@@ -352,8 +352,9 @@ fn main_fn_return_type_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
                 term_id,
                 cause,
             );
-            if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                infcx.report_fulfillment_errors(&err, None, false);
+            let errors = fulfillment_cx.select_all_or_error(&infcx);
+            if !errors.is_empty() {
+                infcx.report_fulfillment_errors(&errors, None, false);
                 error = true;
             }
         });
index 4ab5fe26abe56098cc4210db94e1c804cd90afbc..91727d57ddf4e498364f9c317b42c8b9f3c614b4 100644 (file)
@@ -83,7 +83,8 @@ fn implied_outlives_bounds(
         // variables. Process these constraints.
         let mut fulfill_cx = FulfillmentContext::new();
         fulfill_cx.register_predicate_obligations(self, result.obligations);
-        if fulfill_cx.select_all_or_error(self).is_err() {
+        let errors = fulfill_cx.select_all_or_error(self);
+        if !errors.is_empty() {
             self.tcx.sess.delay_span_bug(
                 span,
                 "implied_outlives_bounds failed to solve obligations from instantiation",
index 8d3862ffc8f01c027907081f5a19ca71d0094c9d..a1c2945770920c1f73dfa6743523e6ebfaa87148 100644 (file)
@@ -300,7 +300,7 @@ fn get_type_or_const_args_suggestions_from_param_names(
                     hir::TyKind::Path(hir::QPath::Resolved(
                         None,
                         hir::Path { res: hir::def::Res::Def(_, id), .. },
-                    )) if *id == def_id => true,
+                    )) => *id == def_id,
                     _ => false,
                 })
             })
index bd4f52560421b9edd0b5935058ebcd4e6474e2da..f6332b072cf30237425386602ce9222d69a9404e 100644 (file)
 #[lang = "owned_box"]
 #[fundamental]
 #[stable(feature = "rust1", since = "1.0.0")]
+// The declaration of the `Box` struct must be kept in sync with the
+// `alloc::alloc::box_free` function or ICEs will happen. See the comment
+// on `box_free` for more details.
 pub struct Box<
     T: ?Sized,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
index 5dda7bfa37c71ea94aabb6a68bd95f6781472fbd..1bb257acff76a905e10207f36b555d3a9262b179 100644 (file)
 #[macro_use]
 mod macros;
 
+mod raw_vec;
+
 // Heaps provided for low-level allocation strategies
 
 pub mod alloc;
@@ -192,7 +194,6 @@ mod boxed {
 pub mod borrow;
 pub mod collections;
 pub mod fmt;
-pub mod raw_vec;
 pub mod rc;
 pub mod slice;
 pub mod str;
index 75dbd4678bb473c39572372c5265a74ae4976ba0..4ab38c802a1599ef507e4bac8aa96d06056fe5d5 100644 (file)
@@ -1,5 +1,4 @@
-#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "none")]
-#![doc(hidden)]
+#![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")]
 
 use core::alloc::LayoutError;
 use core::cmp;
@@ -50,7 +49,7 @@ enum AllocInit {
 /// `usize::MAX`. This means that you need to be careful when round-tripping this type with a
 /// `Box<[T]>`, since `capacity()` won't yield the length.
 #[allow(missing_debug_implementations)]
-pub struct RawVec<T, A: Allocator = Global> {
+pub(crate) struct RawVec<T, A: Allocator = Global> {
     ptr: Unique<T>,
     cap: usize,
     alloc: A,
@@ -87,7 +86,7 @@ pub const fn new() -> Self {
     /// # Aborts
     ///
     /// Aborts on OOM.
-    #[cfg(not(no_global_oom_handling))]
+    #[cfg(not(any(no_global_oom_handling, test)))]
     #[must_use]
     #[inline]
     pub fn with_capacity(capacity: usize) -> Self {
@@ -95,25 +94,12 @@ pub fn with_capacity(capacity: usize) -> Self {
     }
 
     /// Like `with_capacity`, but guarantees the buffer is zeroed.
-    #[cfg(not(no_global_oom_handling))]
+    #[cfg(not(any(no_global_oom_handling, test)))]
     #[must_use]
     #[inline]
     pub fn with_capacity_zeroed(capacity: usize) -> Self {
         Self::with_capacity_zeroed_in(capacity, Global)
     }
-
-    /// Reconstitutes a `RawVec` from a pointer and capacity.
-    ///
-    /// # Safety
-    ///
-    /// The `ptr` must be allocated (on the system heap), and with the given `capacity`.
-    /// The `capacity` cannot exceed `isize::MAX` for sized types. (only a concern on 32-bit
-    /// systems). ZST vectors may have a capacity up to `usize::MAX`.
-    /// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed.
-    #[inline]
-    pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self {
-        unsafe { Self::from_raw_parts_in(ptr, capacity, Global) }
-    }
 }
 
 impl<T, A: Allocator> RawVec<T, A> {
@@ -154,14 +140,6 @@ pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self {
         Self::allocate_in(capacity, AllocInit::Zeroed, alloc)
     }
 
-    /// Converts a `Box<[T]>` into a `RawVec<T>`.
-    pub fn from_box(slice: Box<[T], A>) -> Self {
-        unsafe {
-            let (slice, alloc) = Box::into_raw_with_allocator(slice);
-            RawVec::from_raw_parts_in(slice.as_mut_ptr(), slice.len(), alloc)
-        }
-    }
-
     /// Converts the entire buffer into `Box<[MaybeUninit<T>]>` with the specified `len`.
     ///
     /// Note that this will correctly reconstitute any `cap` changes
@@ -290,37 +268,6 @@ fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
     /// # Aborts
     ///
     /// Aborts on OOM.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(raw_vec_internals)]
-    /// # extern crate alloc;
-    /// # use std::ptr;
-    /// # use alloc::raw_vec::RawVec;
-    /// struct MyVec<T> {
-    ///     buf: RawVec<T>,
-    ///     len: usize,
-    /// }
-    ///
-    /// impl<T: Clone> MyVec<T> {
-    ///     pub fn push_all(&mut self, elems: &[T]) {
-    ///         self.buf.reserve(self.len, elems.len());
-    ///         // reserve would have aborted or panicked if the len exceeded
-    ///         // `isize::MAX` so this is safe to do unchecked now.
-    ///         for x in elems {
-    ///             unsafe {
-    ///                 ptr::write(self.buf.ptr().add(self.len), x.clone());
-    ///             }
-    ///             self.len += 1;
-    ///         }
-    ///     }
-    /// }
-    /// # fn main() {
-    /// #   let mut vector = MyVec { buf: RawVec::new(), len: 0 };
-    /// #   vector.push_all(&[1, 3, 5, 7, 9]);
-    /// # }
-    /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     pub fn reserve(&mut self, len: usize, additional: usize) {
index 4fb2f0c8530d7e983aad7e7dc57c8071d5589f30..03e33a1ff2bc3b77f1223b8056497f8e40763b29 100644 (file)
@@ -313,6 +313,12 @@ pub struct Rc<T: ?Sized> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !marker::Send for Rc<T> {}
+
+// Note that this negative impl isn't strictly necessary for correctness,
+// as `Rc` transitively contains a `Cell`, which is itself `!Sync`.
+// However, given how important `Rc`'s `!Sync`-ness is,
+// having an explicit negative impl is nice for documentation purposes
+// and results in nicer error messages.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !marker::Sync for Rc<T> {}
 
index 7f14f76c8ba6945c052fab77022e6e768b58e0b4..b02ed04a7e915659eea6fb1607df469b84a30638 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7f14f76c8ba6945c052fab77022e6e768b58e0b4
+Subproject commit b02ed04a7e915659eea6fb1607df469b84a30638
index 811850af3678d08480b6678f84a4f683759d6e66..09bb4519170dae3a4891a55182104cd72610952e 100644 (file)
@@ -330,6 +330,47 @@ fn index_mut(&mut self, index: I) -> &mut Self::Output {
     }
 }
 
+#[cfg(not(bootstrap))]
+#[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
+impl<T: Copy, const N: usize> Copy for [T; N] {}
+
+#[cfg(not(bootstrap))]
+#[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
+impl<T: Clone, const N: usize> Clone for [T; N] {
+    #[inline]
+    fn clone(&self) -> Self {
+        SpecArrayClone::clone(self)
+    }
+
+    #[inline]
+    fn clone_from(&mut self, other: &Self) {
+        self.clone_from_slice(other);
+    }
+}
+
+#[cfg(not(bootstrap))]
+trait SpecArrayClone: Clone {
+    fn clone<const N: usize>(array: &[Self; N]) -> [Self; N];
+}
+
+#[cfg(not(bootstrap))]
+impl<T: Clone> SpecArrayClone for T {
+    #[inline]
+    default fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
+        // SAFETY: we know for certain that this iterator will yield exactly `N`
+        // items.
+        unsafe { collect_into_array_unchecked(&mut array.iter().cloned()) }
+    }
+}
+
+#[cfg(not(bootstrap))]
+impl<T: Copy> SpecArrayClone for T {
+    #[inline]
+    fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
+        *array
+    }
+}
+
 // The Default impls cannot be done with const generics because `[T; 0]` doesn't
 // require Default to be implemented, and having different impl blocks for
 // different numbers isn't supported yet.
index d154bb3583c2d387d0757a0acb0fddc47ddbf63b..06dc5ecf2ffa610a4f93509ad05e348c2a56b984 100644 (file)
@@ -240,6 +240,11 @@ pub struct Cell<T: ?Sized> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
 
+// Note that this negative impl isn't strictly necessary for correctness,
+// as `Cell` wraps `UnsafeCell`, which is itself `!Sync`.
+// However, given how important `Cell`'s `!Sync`-ness is,
+// having an explicit negative impl is nice for documentation purposes
+// and results in nicer error messages.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> !Sync for Cell<T> {}
 
index 281ff3badfbd8de32fc47e83cfeec042890dbd67..6f9579043c37d0fc74973ec66a6ea0609598931e 100644 (file)
@@ -93,7 +93,6 @@
 ///
 /// * Function item types (i.e., the distinct types defined for each function)
 /// * Function pointer types (e.g., `fn() -> i32`)
-/// * Array types, for all sizes, if the item type also implements `Clone` (e.g., `[i32; 123456]`)
 /// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`)
 /// * Closure types, if they capture no value from the environment
 ///   or if all such captured values implement `Clone` themselves.
index 91230c027c2d2f6e91031b1af3c397e01c1a00dd..0f57fb5b14180432c3481a91c94b66b74495673f 100644 (file)
@@ -1951,6 +1951,19 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
     !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
 }
 
+/// Checks whether the regions of memory starting at `src` and `dst` of size
+/// `count * size_of::<T>()` do *not* overlap.
+#[cfg(debug_assertions)]
+pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
+    let src_usize = src as usize;
+    let dst_usize = dst as usize;
+    let size = mem::size_of::<T>().checked_mul(count).unwrap();
+    let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
+    // If the absolute distance between the ptrs is at least as big as the size of the buffer,
+    // they do not overlap.
+    diff >= size
+}
+
 /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
 /// and destination must *not* overlap.
 ///
@@ -2042,15 +2055,24 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
         pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
     }
 
-    // FIXME: Perform these checks only at run time
-    /*if cfg!(debug_assertions)
-        && !(is_aligned_and_not_null(src)
-            && is_aligned_and_not_null(dst)
-            && is_nonoverlapping(src, dst, count))
-    {
-        // Not panicking to keep codegen impact smaller.
-        abort();
-    }*/
+    #[cfg(debug_assertions)]
+    fn runtime_check<T>(src: *const T, dst: *mut T, count: usize) {
+        if !is_aligned_and_not_null(src)
+            || !is_aligned_and_not_null(dst)
+            || !is_nonoverlapping(src, dst, count)
+        {
+            // Not panicking to keep codegen impact smaller.
+            abort();
+        }
+    }
+    #[cfg(debug_assertions)]
+    const fn compiletime_check<T>(_src: *const T, _dst: *mut T, _count: usize) {}
+    #[cfg(debug_assertions)]
+    // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to
+    // not do them during compile time
+    unsafe {
+        const_eval_select((src, dst, count), compiletime_check, runtime_check);
+    }
 
     // SAFETY: the safety contract for `copy_nonoverlapping` must be
     // upheld by the caller.
@@ -2127,11 +2149,21 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
         fn copy<T>(src: *const T, dst: *mut T, count: usize);
     }
 
-    // FIXME: Perform these checks only at run time
-    /*if cfg!(debug_assertions) && !(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)) {
-        // Not panicking to keep codegen impact smaller.
-        abort();
-    }*/
+    #[cfg(debug_assertions)]
+    fn runtime_check<T>(src: *const T, dst: *mut T) {
+        if !is_aligned_and_not_null(src) || !is_aligned_and_not_null(dst) {
+            // Not panicking to keep codegen impact smaller.
+            abort();
+        }
+    }
+    #[cfg(debug_assertions)]
+    const fn compiletime_check<T>(_src: *const T, _dst: *mut T) {}
+    #[cfg(debug_assertions)]
+    // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to
+    // not do them during compile time
+    unsafe {
+        const_eval_select((src, dst), compiletime_check, runtime_check);
+    }
 
     // SAFETY: the safety contract for `copy` must be upheld by the caller.
     unsafe { copy(src, dst, count) }
index 1be842d84b148cf2b1abfa24ba52720335f0c420..584b90d613f6b1583a50824fbb3ed64ffef08b68 100644 (file)
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_discriminant)]
-#![cfg_attr(not(bootstrap), feature(const_eval_select))]
+#![feature(const_eval_select)]
 #![feature(const_float_bits_conv)]
 #![feature(const_float_classify)]
 #![feature(const_fmt_arguments_new)]
 #![feature(try_blocks)]
 #![feature(unboxed_closures)]
 #![feature(unsized_fn_params)]
+#![cfg_attr(not(bootstrap), feature(asm_const))]
 //
 // Target features:
 #![feature(aarch64_target_feature)]
@@ -391,4 +392,25 @@ pub mod arch {
     }
 }
 
+// Pull in the `core_simd` crate directly into libcore. The contents of
+// `core_simd` are in a different repository: rust-lang/portable-simd.
+//
+// `core_simd` depends on libcore, but the contents of this module are
+// set up in such a way that directly pulling it here works such that the
+// crate uses this crate as its libcore.
+#[path = "../../portable-simd/crates/core_simd/src/mod.rs"]
+#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)]
+#[allow(rustdoc::bare_urls)]
+#[unstable(feature = "portable_simd", issue = "86656")]
+#[cfg(not(bootstrap))]
+mod core_simd;
+
+#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")]
+#[unstable(feature = "portable_simd", issue = "86656")]
+#[cfg(not(bootstrap))]
+pub mod simd {
+    #[unstable(feature = "portable_simd", issue = "86656")]
+    pub use crate::core_simd::simd::*;
+}
+
 include!("primitive_docs.rs");
index 5b3e988caa506cc61e8c74f069e30e9ca3711649..993ae72322966388b96342c7038256d3d509576a 100644 (file)
@@ -554,7 +554,10 @@ macro_rules! writeln {
 ///
 /// # Panics
 ///
-/// This will always [`panic!`].
+/// This will always [`panic!`] because `unreachable!` is just a shorthand for `panic!` with a
+/// fixed, specific message.
+///
+/// Like `panic!`, this macro has a second form for displaying custom values.
 ///
 /// # Examples
 ///
@@ -581,7 +584,7 @@ macro_rules! writeln {
 ///         if 3*i < i { panic!("u32 overflow"); }
 ///         if x < 3*i { return i-1; }
 ///     }
-///     unreachable!();
+///     unreachable!("The loop should always return");
 /// }
 /// ```
 #[macro_export]
index 37446bafacb240740873234b3f51dce261457b67..71eea43aa54e1451a46d4eb23d0255a834bd4839 100644 (file)
@@ -359,7 +359,6 @@ pub trait StructuralEq {
 ///
 /// * Function item types (i.e., the distinct types defined for each function)
 /// * Function pointer types (e.g., `fn() -> i32`)
-/// * Array types, for all sizes, if the item type also implements `Copy` (e.g., `[i32; 123456]`)
 /// * Tuple types, if each component also implements `Copy` (e.g., `()`, `(i32, bool)`)
 /// * Closure types, if they capture no value from the environment
 ///   or if all such captured values implement `Copy` themselves.
index adc64cb2bd39a85196791aa7164ea7021cee00fa..5d5527dc8b46b698f55942bbf8e03fc8596ad347 100644 (file)
@@ -1092,8 +1092,9 @@ pub unsafe fn replace(self, src: T) -> T
     ///
     /// [`ptr::swap`]: crate::ptr::swap()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
+    #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
     #[inline(always)]
-    pub unsafe fn swap(self, with: *mut T)
+    pub const unsafe fn swap(self, with: *mut T)
     where
         T: Sized,
     {
index 65ed72cb0cdbe24ca0a2bf493ca1db779ac0cce3..d876d944e7f0b8747627433cae07b8272f39d6eb 100644 (file)
@@ -558,8 +558,9 @@ pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
     /// assert!(v == ["a", "b", "e", "d", "c"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
     #[inline]
-    pub fn swap(&mut self, a: usize, b: usize) {
+    pub const fn swap(&mut self, a: usize, b: usize) {
         let _ = &self[a];
         let _ = &self[b];
 
@@ -595,7 +596,8 @@ pub fn swap(&mut self, a: usize, b: usize) {
     /// [`swap`]: slice::swap
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     #[unstable(feature = "slice_swap_unchecked", issue = "88539")]
-    pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
+    #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+    pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
         #[cfg(debug_assertions)]
         {
             let _ = &self[a];
index b201cfeb038f16519b8b6d6d43364f5d16481ea4..b9acd0d29903d6d14c50c19167b8a2d80d3d9cb5 100644 (file)
@@ -60,6 +60,7 @@
 #![feature(never_type)]
 #![feature(unwrap_infallible)]
 #![feature(result_into_ok_or_err)]
+#![cfg_attr(not(bootstrap), feature(portable_simd))]
 #![feature(ptr_metadata)]
 #![feature(once_cell)]
 #![feature(unsized_tuple_coercion)]
 mod pin;
 mod ptr;
 mod result;
+#[cfg(not(bootstrap))]
+mod simd;
 mod slice;
 mod str;
 mod str_lossy;
diff --git a/library/core/tests/simd.rs b/library/core/tests/simd.rs
new file mode 100644 (file)
index 0000000..8c11d78
--- /dev/null
@@ -0,0 +1,13 @@
+use core::simd::f32x4;
+
+#[test]
+fn testing() {
+    let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]);
+    let y = -x;
+
+    let h = x * 0.5;
+
+    let r = y.abs();
+    assert_eq!(x, r);
+    assert_eq!(h, f32x4::splat(0.5));
+}
diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/blank_issue.md b/library/portable-simd/.github/ISSUE_TEMPLATE/blank_issue.md
new file mode 100644 (file)
index 0000000..9aef3eb
--- /dev/null
@@ -0,0 +1,4 @@
+---
+name: Blank Issue
+about: Create a blank issue.
+---
diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/bug_report.md b/library/portable-simd/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644 (file)
index 0000000..16a8251
--- /dev/null
@@ -0,0 +1,50 @@
+---
+name: Bug Report
+about: Create a bug report for Rust.
+labels: C-bug
+---
+<!--
+Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
+along with any information you feel relevant to replicating the bug.
+-->
+
+I tried this code:
+
+```rust
+<code>
+```
+
+I expected to see this happen: *explanation*
+
+Instead, this happened: *explanation*
+
+### Meta
+
+`rustc --version --verbose`:
+```
+<version>
+```
+
+
+`crate version in Cargo.toml`:
+```toml
+[dependencies]
+stdsimd = 
+```
+<!-- If this specifies the repo at HEAD, please include the latest commit. -->
+
+
+<!--
+If a backtrace is available, please include a backtrace in the code block by
+setting `RUST_BACKTRACE=1` in your environment. e.g.
+`RUST_BACKTRACE=1 cargo build`.
+-->
+<details><summary>Backtrace</summary>
+<p>
+
+```
+<backtrace>
+```
+
+</p>
+</details>
diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/config.yml b/library/portable-simd/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644 (file)
index 0000000..1567542
--- /dev/null
@@ -0,0 +1,10 @@
+# This only controls whether a tiny, hard-to-find "open a blank issue" link appears at the end of
+# the template list.
+blank_issues_enabled: true
+contact_links:
+  - name: Intrinsic Support
+    url: https://github.com/rust-lang/stdarch/issues
+    about: Please direct issues about Rust's support for vendor intrinsics to core::arch
+  - name: Internal Compiler Error
+    url: https://github.com/rust-lang/rust/issues
+    about: Please report ICEs to the rustc repository
diff --git a/library/portable-simd/.github/ISSUE_TEMPLATE/feature_request.md b/library/portable-simd/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644 (file)
index 0000000..be6c9e3
--- /dev/null
@@ -0,0 +1,14 @@
+---
+name: Feature Request
+about: Request an addition to the core::simd API
+labels: C-feature-request
+---
+<!--
+  Hello!
+
+  We are very interested in any feature requests you may have.
+
+  However, please be aware that core::simd exists to address concerns with creating a portable SIMD API for Rust.
+  Requests for extensions to compiler features, such as `target_feature`, binary versioning for SIMD APIs, or
+  improving specific compilation issues in general should be discussed at https://internals.rust-lang.org/
+-->
diff --git a/library/portable-simd/.github/PULL_REQUEST_TEMPLATE.md b/library/portable-simd/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644 (file)
index 0000000..31422b7
--- /dev/null
@@ -0,0 +1,18 @@
+Hello, welcome to `std::simd`!
+
+It seems this pull request template checklist was created while a lot of vector math ops were being implemented, and only really applies to ops. Feel free to delete everything here if it's not applicable, or ask for help if you're not sure what it means!
+
+For a given vector math operation on TxN, please add tests for interactions with:
+  - [ ] `T::MAX`
+  - [ ] `T::MIN`
+  - [ ] -1
+  - [ ] 1
+  - [ ] 0
+
+
+For a given vector math operation on TxN where T is a float, please add tests for test interactions with:
+  - [ ] a really large number, larger than the mantissa
+  - [ ] a really small "subnormal" number
+  - [ ] NaN
+  - [ ] Infinity
+  - [ ] Negative Infinity
diff --git a/library/portable-simd/.github/workflows/ci.yml b/library/portable-simd/.github/workflows/ci.yml
new file mode 100644 (file)
index 0000000..d50dfa1
--- /dev/null
@@ -0,0 +1,260 @@
+name: CI
+
+on:
+  pull_request:
+  push:
+    branches:
+      - master
+
+env:
+  CARGO_NET_RETRY: 10
+  RUSTUP_MAX_RETRIES: 10
+
+jobs:
+  rustfmt:
+    name: "rustfmt"
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Setup Rust
+        run: |
+          rustup update nightly --no-self-update
+          rustup default nightly
+          rustup component add rustfmt
+      - name: Run rustfmt
+        run: cargo fmt --all -- --check
+
+  clippy:
+    name: "clippy on ${{ matrix.target }}"
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        target:
+          # We shouldn't really have any OS-specific code, so think of this as a list of architectures
+          - x86_64-unknown-linux-gnu
+          - i686-unknown-linux-gnu
+          - i586-unknown-linux-gnu
+          - aarch64-unknown-linux-gnu
+          - armv7-unknown-linux-gnueabihf
+          - mips-unknown-linux-gnu
+          - mips64-unknown-linux-gnuabi64
+          - powerpc-unknown-linux-gnu
+          - powerpc64-unknown-linux-gnu
+          - riscv64gc-unknown-linux-gnu
+          - s390x-unknown-linux-gnu
+          - sparc64-unknown-linux-gnu
+          - wasm32-unknown-unknown
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Setup Rust
+        run: |
+          rustup update nightly --no-self-update
+          rustup default nightly
+          rustup target add ${{ matrix.target }}
+          rustup component add clippy
+      - name: Run Clippy
+        run: cargo clippy --all-targets --target ${{ matrix.target }}
+
+  x86-tests:
+    name: "${{ matrix.target_feature }} on ${{ matrix.target }}"
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, i586-pc-windows-msvc, x86_64-unknown-linux-gnu, x86_64-apple-darwin]
+        # `default` means we use the default target config for the target,
+        # `native` means we run with `-Ctarget-cpu=native`, and anything else is
+        # an arg to `-Ctarget-feature`
+        target_feature: [default, native, +sse3, +ssse3, +sse4.1, +sse4.2, +avx, +avx2]
+
+        exclude:
+          # The macos runners seem to only reliably support up to `avx`.
+          - { target: x86_64-apple-darwin, target_feature: +avx2 }
+          # These features are statically known to be present for all 64 bit
+          # macs, and thus are covered by the `default` test
+          - { target: x86_64-apple-darwin, target_feature: +sse3 }
+          - { target: x86_64-apple-darwin, target_feature: +ssse3 }
+          # -Ctarget-cpu=native sounds like bad-news if target != host
+          - { target: i686-pc-windows-msvc, target_feature: native }
+          - { target: i586-pc-windows-msvc, target_feature: native }
+
+        include:
+          # Populate the `matrix.os` field
+          - { target: x86_64-apple-darwin,      os: macos-latest }
+          - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest }
+          - { target: x86_64-pc-windows-msvc,   os: windows-latest }
+          - { target: i686-pc-windows-msvc,     os: windows-latest }
+          - { target: i586-pc-windows-msvc,     os: windows-latest }
+
+          # These are globally available on all the other targets.
+          - { target: i586-pc-windows-msvc, target_feature: +sse, os: windows-latest }
+          - { target: i586-pc-windows-msvc, target_feature: +sse2, os: windows-latest }
+
+          # Annoyingly, the x86_64-unknown-linux-gnu runner *almost* always has
+          # avx512vl, but occasionally doesn't.  Maybe one day we can enable it.
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Setup Rust
+        run: |
+          rustup update nightly --no-self-update
+          rustup default nightly
+          rustup target add ${{ matrix.target }}
+
+      - name: Configure RUSTFLAGS
+        shell: bash
+        run: |
+          case "${{ matrix.target_feature }}" in
+            default)
+              echo "RUSTFLAGS=-Dwarnings" >> $GITHUB_ENV;;
+            native)
+              echo "RUSTFLAGS=-Dwarnings -Ctarget-cpu=native" >> $GITHUB_ENV
+              ;;
+            *)
+              echo "RUSTFLAGS=-Dwarnings -Ctarget-feature=${{ matrix.target_feature }}" >> $GITHUB_ENV
+              ;;
+          esac
+
+      # Super useful for debugging why a SIGILL occurred.
+      - name: Dump target configuration and support
+        run: |
+          rustc -Vv
+
+          echo "Caveat: not all target features are expected to be logged"
+
+          echo "## Requested target configuration (RUSTFLAGS=$RUSTFLAGS)"
+          rustc --print=cfg --target=${{ matrix.target }} $RUSTFLAGS
+
+          echo "## Supported target configuration for --target=${{ matrix.target }}"
+          rustc --print=cfg --target=${{ matrix.target }} -Ctarget-cpu=native
+
+          echo "## Natively supported target configuration"
+          rustc --print=cfg -Ctarget-cpu=native
+
+      - name: Test (debug)
+        run: cargo test --verbose --target=${{ matrix.target }}
+
+      - name: Test (release)
+        run: cargo test --verbose --target=${{ matrix.target }} --release
+
+  wasm-tests:
+    name: "wasm (firefox, ${{ matrix.name }})"
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        include:
+          - { name: default, RUSTFLAGS: "" }
+          - { name: simd128, RUSTFLAGS: "-C target-feature=+simd128" }
+    steps:
+      - uses: actions/checkout@v2
+      - name: Setup Rust
+        run: |
+          rustup update nightly --no-self-update
+          rustup default nightly
+      - name: Install wasm-pack
+        run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+      - name: Test (debug)
+        run: wasm-pack test --firefox --headless crates/core_simd
+        env:
+            RUSTFLAGS: ${{ matrix.rustflags }}
+      - name: Test (release)
+        run: wasm-pack test --firefox --headless crates/core_simd --release
+        env:
+            RUSTFLAGS: ${{ matrix.rustflags }}
+
+  cross-tests:
+    name: "${{ matrix.target }} (via cross)"
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      # TODO: Sadly, we cant configure target-feature in a meaningful way
+      # because `cross` doesn't tell qemu to enable any non-default cpu
+      # features, nor does it give us a way to do so.
+      #
+      # Ultimately, we'd like to do something like [rust-lang/stdarch][stdarch].
+      # This is a lot more complex... but in practice it's likely that we can just
+      # snarf the docker config from around [here][1000-dockerfiles].
+      #
+      # [stdarch]: https://github.com/rust-lang/stdarch/blob/a5db4eaf/.github/workflows/main.yml#L67
+      # [1000-dockerfiles]: https://github.com/rust-lang/stdarch/tree/a5db4eaf/ci/docker
+
+      matrix:
+        target:
+          - i586-unknown-linux-gnu
+          # 32-bit arm has a few idiosyncracies like having subnormal flushing
+          # to zero on by default. Ideally we'd set
+          - armv7-unknown-linux-gnueabihf
+          - aarch64-unknown-linux-gnu
+          # Note: The issue above means neither of these mips targets will use
+          # MSA (mips simd) but MIPS uses a nonstandard binary representation
+          # for NaNs which makes it worth testing on despite that.
+          - mips-unknown-linux-gnu
+          - mips64-unknown-linux-gnuabi64
+          - riscv64gc-unknown-linux-gnu
+          # TODO this test works, but it appears to time out
+          # - powerpc-unknown-linux-gnu
+          # TODO this test is broken, but it appears to be a problem with QEMU, not us.
+          # - powerpc64le-unknown-linux-gnu
+          # TODO enable this once a new version of cross is released
+          # - powerpc64-unknown-linux-gnu
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Setup Rust
+        run: |
+          rustup update nightly --no-self-update
+          rustup default nightly
+          rustup target add ${{ matrix.target }}
+          rustup component add rust-src
+
+      - name: Install Cross
+        # Equivalent to `cargo install cross`, but downloading a prebuilt
+        # binary. Ideally we wouldn't hardcode a version, but the version number
+        # being part of the tarball means we can't just use the download/latest
+        # URL :(
+        run: |
+          CROSS_URL=https://github.com/rust-embedded/cross/releases/download/v0.2.1/cross-v0.2.1-x86_64-unknown-linux-gnu.tar.gz
+          mkdir -p "$HOME/.bin"
+          curl -sfSL --retry-delay 10 --retry 5 "${CROSS_URL}" | tar zxf - -C "$HOME/.bin"
+          echo "$HOME/.bin" >> $GITHUB_PATH
+
+      - name: Test (debug)
+        run: cross test --verbose --target=${{ matrix.target }}
+
+      - name: Test (release)
+        run: cross test --verbose --target=${{ matrix.target }} --release
+
+  features:
+    name: "Check cargo features (${{ matrix.simd }} × ${{ matrix.features }})"
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        simd:
+          - ""
+          - "avx512"
+        features:
+          - ""
+          - "--features std"
+          - "--features generic_const_exprs"
+          - "--features std --features generic_const_exprs"
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Setup Rust
+        run: |
+          rustup update nightly --no-self-update
+          rustup default nightly
+      - name: Detect AVX512
+        run: echo "CPU_FEATURE=$(lscpu | grep -o avx512[a-z]* | sed s/avx/+avx/ | tr '\n' ',' )" >> $GITHUB_ENV
+      - name: Check build
+        if: ${{ matrix.simd == '' }}
+        run: RUSTFLAGS="-Dwarnings" cargo check --all-targets --no-default-features ${{ matrix.features }}
+      - name: Check AVX
+        if: ${{ matrix.simd == 'avx512' && contains(env.CPU_FEATURE, 'avx512') }}
+        run: |
+          echo "Found AVX features: $CPU_FEATURE"
+          RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo check --all-targets --no-default-features ${{ matrix.features }}
diff --git a/library/portable-simd/.github/workflows/doc.yml b/library/portable-simd/.github/workflows/doc.yml
new file mode 100644 (file)
index 0000000..9d1fa66
--- /dev/null
@@ -0,0 +1,30 @@
+name: Documentation
+
+on:
+  push:
+    branches:
+      - master
+
+jobs:
+  release:
+    name: Deploy Documentation
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout Repository
+        uses: actions/checkout@v1
+
+      - name: Setup Rust
+        run: |
+          rustup update nightly --no-self-update
+          rustup default nightly
+
+      - name: Build Documentation
+        run: cargo doc --no-deps
+      
+      - name: Deploy Documentation
+        uses: peaceiris/actions-gh-pages@v3
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          publish_branch: gh-pages
+          publish_dir: ./target/doc
diff --git a/library/portable-simd/.gitignore b/library/portable-simd/.gitignore
new file mode 100644 (file)
index 0000000..96ef6c0
--- /dev/null
@@ -0,0 +1,2 @@
+/target
+Cargo.lock
diff --git a/library/portable-simd/CONTRIBUTING.md b/library/portable-simd/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..f9ba12d
--- /dev/null
@@ -0,0 +1,32 @@
+# Contributing to `std::simd`
+
+Simple version:
+1. Fork it and `git clone` it
+2. Create your feature branch: `git checkout -b my-branch`
+3. Write your changes.
+4. Test it: `cargo test`. Remember to enable whatever SIMD features you intend to test by setting `RUSTFLAGS`.
+5. Commit your changes: `git commit add ./path/to/changes && git commit -m 'Fix some bug'`
+6. Push the branch: `git push --set-upstream origin my-branch`
+7. Submit a pull request!
+
+## Taking on an Issue
+
+SIMD can be quite complex, and even a "simple" issue can be huge. If an issue is organized like a tracking issue, with an itemized list of items that don't necessarily have to be done in a specific order, please take the issue one item at a time. This will help by letting work proceed apace on the rest of the issue. If it's a (relatively) small issue, feel free to announce your intention to solve it on the issue tracker and take it in one go!
+
+## CI
+
+We currently have 2 CI matrices through Travis CI and GitHub Actions that will automatically build and test your change in order to verify that `std::simd`'s portable API is, in fact, portable. If your change builds locally, but does not build on either, this is likely due to a platform-specific concern that your code has not addressed. Please consult the build logs and address the error, or ask for help if you need it.
+
+## Beyond stdsimd
+
+A large amount of the core SIMD implementation is found in the rustc_codegen_* crates in the [main rustc repo](https://github.com/rust-lang/rust). In addition, actual platform-specific functions are implemented in [stdarch]. Not all changes to `std::simd` require interacting with either of these, but if you're wondering where something is and it doesn't seem to be in this repository, those might be where to start looking.
+
+## Questions? Concerns? Need Help?
+
+Please feel free to ask in the [#project-portable-simd][zulip-portable-simd] stream on the [rust-lang Zulip][zulip] for help with making changes to `std::simd`!
+If your changes include directly modifying the compiler, it might also be useful to ask in [#t-compiler/help][zulip-compiler-help].
+
+[zulip-portable-simd]: https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd
+[zulip-compiler-help]: https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp
+[zulip]: https://rust-lang.zulipchat.com
+[stdarch]: https://github.com/rust-lang/stdarch
diff --git a/library/portable-simd/Cargo.toml b/library/portable-simd/Cargo.toml
new file mode 100644 (file)
index 0000000..3f1abd7
--- /dev/null
@@ -0,0 +1,6 @@
+[workspace]
+
+members = [
+    "crates/core_simd",
+    "crates/test_helpers",
+]
diff --git a/library/portable-simd/LICENSE-APACHE b/library/portable-simd/LICENSE-APACHE
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/library/portable-simd/LICENSE-MIT b/library/portable-simd/LICENSE-MIT
new file mode 100644 (file)
index 0000000..0e9d2f4
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2020 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/library/portable-simd/README.md b/library/portable-simd/README.md
new file mode 100644 (file)
index 0000000..da536a4
--- /dev/null
@@ -0,0 +1,69 @@
+# The Rust standard library's portable SIMD API
+[![Build Status](https://travis-ci.com/rust-lang/portable-simd.svg?branch=master)](https://travis-ci.com/rust-lang/portable-simd)
+
+Code repository for the [Portable SIMD Project Group](https://github.com/rust-lang/project-portable-simd).
+Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) for our contributing guidelines.
+
+The docs for this crate are published from the main branch.
+You can [read them here][docs].
+
+If you have questions about SIMD, we have begun writing a [guide][simd-guide].
+We can also be found on [Zulip][zulip-project-portable-simd].
+
+If you are interested in support for a specific architecture, you may want [stdarch] instead.
+
+## Hello World
+
+Now we're gonna dip our toes into this world with a small SIMD "Hello, World!" example. Make sure your compiler is up to date and using `nightly`. We can do that by running 
+
+```bash
+rustup update -- nightly
+```
+
+or by setting up `rustup default nightly` or else with `cargo +nightly {build,test,run}`. After updating, run 
+```bash
+cargo new hellosimd
+```
+to create a new crate. Edit `hellosimd/Cargo.toml` to be 
+```toml
+[package]
+name = "hellosimd"
+version = "0.1.0"
+edition = "2018"
+[dependencies]
+core_simd = { git = "https://github.com/rust-lang/portable-simd" }
+```
+
+and finally write this in `src/main.rs`:
+```rust
+use core_simd::*;
+fn main() {
+    let a = f32x4::splat(10.0);
+    let b = f32x4::from_array([1.0, 2.0, 3.0, 4.0]);
+    println!("{:?}", a + b);
+}
+```
+
+Explanation: We import all the bindings from the crate with the first line. Then, we construct our SIMD vectors with methods like `splat` or `from_array`. Finally, we can use operators on them like `+` and the appropriate SIMD instructions will be carried out. When we run `cargo run` you should get `[11.0, 12.0, 13.0, 14.0]`.
+
+## Code Organization
+
+Currently the crate is organized so that each element type is a file, and then the 64-bit, 128-bit, 256-bit, and 512-bit vectors using those types are contained in said file.
+
+All types are then exported as a single, flat module.
+
+Depending on the size of the primitive type, the number of lanes the vector will have varies. For example, 128-bit vectors have four `f32` lanes and two `f64` lanes.
+
+The supported element types are as follows:
+* **Floating Point:** `f32`, `f64`
+* **Signed Integers:** `i8`, `i16`, `i32`, `i64`, `i128`, `isize`
+* **Unsigned Integers:** `u8`, `u16`, `u32`, `u64`, `u128`, `usize`
+* **Masks:** `mask8`, `mask16`, `mask32`, `mask64`, `mask128`, `masksize`
+
+Floating point, signed integers, and unsigned integers are the [primitive types](https://doc.rust-lang.org/core/primitive/index.html) you're already used to.
+The `mask` types are "truthy" values, but they use the number of bits in their name instead of just 1 bit like a normal `bool` uses.
+
+[simd-guide]: ./beginners-guide.md
+[zulip-project-portable-simd]: https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd
+[stdarch]: https://github.com/rust-lang/stdarch
+[docs]: https://rust-lang.github.io/portable-simd/core_simd
diff --git a/library/portable-simd/beginners-guide.md b/library/portable-simd/beginners-guide.md
new file mode 100644 (file)
index 0000000..dfd357c
--- /dev/null
@@ -0,0 +1,86 @@
+
+# Beginner's Guide To SIMD
+
+Hello and welcome to our SIMD basics guide!
+
+Because SIMD is a subject that many programmers haven't worked with before, we thought that it's best to outline some terms and other basics for you to get started with.
+
+## Quick Background
+
+**SIMD** stands for *Single Instruction, Multiple Data*. In other words, SIMD is when the CPU performs a single action on more than one logical piece of data at the same time. Instead of adding two registers that each contain one `f32` value and getting an `f32` as the result, you might add two registers that each contain `f32x4` (128 bits of data) and then you get an `f32x4` as the output.
+
+This might seem a tiny bit weird at first, but there's a good reason for it. Back in the day, as CPUs got faster and faster, eventually they got so fast that the CPU would just melt itself. The heat management (heat sinks, fans, etc) simply couldn't keep up with how much electricity was going through the metal. Two main strategies were developed to help get around the limits of physics.
+* One of them you're probably familiar with: Multi-core processors. By giving a processor more than one core, each core can do its own work, and because they're physically distant (at least on the CPU's scale) the heat can still be managed. Unfortunately, not all tasks can just be split up across cores in an efficient way.
+* The second strategy is SIMD. If you can't make the register go any faster, you can still make the register *wider*. This lets you process more data at a time, which is *almost* as good as just having a faster CPU. As with multi-core programming, SIMD doesn't fit every kind of task, so you have to know when it will improve your program.
+
+## Terms
+
+SIMD has a few special vocabulary terms you should know:
+
+* **Vector:** A SIMD value is called a vector. This shouldn't be confused with the `Vec<T>` type. A SIMD vector has a fixed size, known at compile time. All of the elements within the vector are of the same type. This makes vectors *similar to* arrays. One difference is that a vector is generally aligned to its *entire* size (eg: 16 bytes, 32 bytes, etc), not just the size of an individual element. Sometimes vector data is called "packed" data.
+
+* **Vectorize**: An operation that uses SIMD instructions to operate over a vector is often referred to as "vectorized".
+
+* **Autovectorization**: Also known as _implicit vectorization_. This is when a compiler can automatically recognize a situation where scalar instructions may be replaced with SIMD instructions, and use those instead.
+
+* **Scalar:** "Scalar" in mathematical contexts refers to values that can be represented as a single element, mostly numbers like 6, 3.14, or -2. It can also be used to describe "scalar operations" that use strictly scalar values, like addition. This term is mostly used to differentiate between vectorized operations that use SIMD instructions and scalar operations that don't.
+
+* **Lane:** A single element position within a vector is called a lane. If you have `N` lanes available then they're numbered from `0` to `N-1` when referring to them, again like an array. The biggest difference between an array element and a vector lane is that in general is *relatively costly* to access an individual lane value. On most architectures, the vector has to be pushed out of the SIMD register onto the stack, then an individual lane is accessed while it's on the stack (and possibly the stack value is read back into a register). For this reason, when working with SIMD you should avoid reading or writing the value of an individual lane during hot loops.
+
+* **Bit Widths:** When talking about SIMD, the bit widths used are the bit size of the vectors involved, *not* the individual elements. So "128-bit SIMD" has 128-bit vectors, and that might be `f32x4`, `i32x4`, `i16x8`, or other variations. While 128-bit SIMD is the most common, there's also 64-bit, 256-bit, and even 512-bit on the newest CPUs.
+
+* **Vector Register:** The extra-wide registers that are used for SIMD operations are commonly called vector registers, though you may also see "SIMD registers", vendor names for specific features, or even "floating-point register" as it is common for the same registers to be used with both scalar and vectorized floating-point operations.
+
+* **Vertical:** When an operation is "vertical", each lane processes individually without regard to the other lanes in the same vector. For example, a "vertical add" between two vectors would add lane 0 in `a` with lane 0 in `b`, with the total in lane 0 of `out`, and then the same thing for lanes 1, 2, etc. Most SIMD operations are vertical operations, so if your problem is a vertical problem then you can probably solve it with SIMD.
+
+* **Horizontal:** When an operation is "horizontal", the lanes within a single vector interact in some way. A "horizontal add" might add up lane 0 of `a` with lane 1 of `a`, with the total in lane 0 of `out`.
+
+* **Target Feature:** Rust calls a CPU architecture extension a `target_feature`. Proper SIMD requires various CPU extensions to be enabled (details below). Don't confuse this with `feature`, which is a Cargo crate concept.
+
+## Target Features
+
+When using SIMD, you should be familiar with the CPU feature set that you're targeting.
+
+On `arm` and `aarch64` it's fairly simple. There's just one CPU feature that controls if SIMD is available: `neon` (or "NEON", all caps, as the ARM docs often put it). Neon registers can be used as 64-bit or 128-bit. When doing 128-bit operations it just uses two 64-bit registers as a single 128-bit register.
+
+> By default, the `aarch64`, `arm`, and `thumb` Rust targets generally do not enable `neon` unless it's in the target string.
+
+On `x86` and `x86_64` it's slightly more complicated. The SIMD support is split into many levels:
+* 128-bit: `sse`, `sse2`, `sse3`, `ssse3` (not a typo!), `sse4.1`, `sse4.2`, `sse4a` (AMD only)
+* 256-bit (mostly): `avx`, `avx2`, `fma`
+* 512-bit (mostly): a *wide* range of `avx512` variations
+
+The list notes the bit widths available at each feature level, though the operations of the more advanced features can generally be used with the smaller register sizes as well. For example, new operations introduced in `avx` generally have a 128-bit form as well as a 256-bit form. This means that even if you only do 128-bit work you can still benefit from the later feature levels.
+
+> By default, the `i686` and `x86_64` Rust targets enable `sse` and `sse2`.
+
+### Selecting Additional Target Features
+
+If you want to enable support for a target feature within your build, generally you should use a [target-feature](https://rust-lang.github.io/packed_simd/perf-guide/target-feature/rustflags.html#target-feature) setting within you `RUSTFLAGS` setting.
+
+If you know that you're targeting a specific CPU you can instead use the [target-cpu](https://rust-lang.github.io/packed_simd/perf-guide/target-feature/rustflags.html#target-cpu) flag and the compiler will enable the correct set of features for that CPU.
+
+The [Steam Hardware Survey](https://store.steampowered.com/hwsurvey/Steam-Hardware-Software-Survey-Welcome-to-Steam) is one of the few places with data on how common various CPU features are. The dataset is limited to "the kinds of computers owned by people who play computer games", so the info only covers `x86`/`x86_64`, and it also probably skews to slightly higher quality computers than average. Still, we can see that the `sse` levels have very high support, `avx` and `avx2` are quite common as well, and the `avx-512` family is still so early in adoption you can barely find it in consumer grade stuff.
+
+## Running a program compiled for a CPU feature level that the CPU doesn't support is automatic undefined behavior.
+
+This means that if you build your program with `avx` support enabled and run it on a CPU without `avx` support, it's **instantly** undefined behavior.
+
+Even without an `unsafe` block in sight.
+
+This is no bug in Rust, or soundness hole in the type system. You just plain can't make a CPU do what it doesn't know how to do.
+
+This is why the various Rust targets *don't* enable many CPU feature flags by default: requiring a more advanced CPU makes the final binary *less* portable.
+
+So please select an appropriate CPU feature level when building your programs.
+
+## Size, Alignment, and Unsafe Code
+
+Most of the portable SIMD API is designed to allow the user to gloss over the details of different architectures and avoid using unsafe code. However, there are plenty of reasons to want to use unsafe code with these SIMD types, such as using an intrinsic function from `core::arch` to further accelerate particularly specialized SIMD operations on a given platform, while still using the portable API elsewhere. For these cases, there are some rules to keep in mind.
+
+Fortunately, most SIMD types have a fairly predictable size. `i32x4` is bit-equivalent to `[i32; 4]` and so can be bitcast to it, e.g. using [`mem::transmute`], though the API usually offers a safe cast you can use instead.
+
+However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`mem::align_of`].
+
+[`mem::transmute`]: https://doc.rust-lang.org/core/mem/fn.transmute.html
+[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html
\ No newline at end of file
diff --git a/library/portable-simd/crates/core_simd/Cargo.toml b/library/portable-simd/crates/core_simd/Cargo.toml
new file mode 100644 (file)
index 0000000..a103ef1
--- /dev/null
@@ -0,0 +1,28 @@
+[package]
+name = "core_simd"
+version = "0.1.0"
+edition = "2021"
+homepage = "https://github.com/rust-lang/portable-simd"
+repository = "https://github.com/rust-lang/portable-simd"
+keywords = ["core", "simd", "intrinsics"]
+categories = ["hardware-support", "no-std"]
+license = "MIT OR Apache-2.0"
+
+[features]
+default = ["std", "generic_const_exprs"]
+std = []
+generic_const_exprs = []
+
+[target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen]
+version = "0.2"
+
+[dev-dependencies.wasm-bindgen-test]
+version = "0.3"
+
+[dev-dependencies.proptest]
+version = "0.10"
+default-features = false
+features = ["alloc"]
+
+[dev-dependencies.test_helpers]
+path = "../test_helpers"
diff --git a/library/portable-simd/crates/core_simd/LICENSE-APACHE b/library/portable-simd/crates/core_simd/LICENSE-APACHE
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/library/portable-simd/crates/core_simd/LICENSE-MIT b/library/portable-simd/crates/core_simd/LICENSE-MIT
new file mode 100644 (file)
index 0000000..0e9d2f4
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2020 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs b/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs
new file mode 100644 (file)
index 0000000..c51a566
--- /dev/null
@@ -0,0 +1,316 @@
+//! 4x4 matrix inverse
+// Code ported from the `packed_simd` crate
+// Run this code with `cargo test --example matrix_inversion`
+#![feature(array_chunks, portable_simd)]
+use core_simd::simd::*;
+use Which::*;
+
+// Gotta define our own 4x4 matrix since Rust doesn't ship multidim arrays yet :^)
+#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
+pub struct Matrix4x4([[f32; 4]; 4]);
+
+#[allow(clippy::too_many_lines)]
+pub fn scalar_inv4x4(m: Matrix4x4) -> Option<Matrix4x4> {
+    let m = m.0;
+
+    #[rustfmt::skip]
+    let mut inv = [
+        // row 0:
+        [
+            // 0,0:
+            m[1][1] * m[2][2] * m[3][3] -
+            m[1][1] * m[2][3] * m[3][2] -
+            m[2][1] * m[1][2] * m[3][3] +
+            m[2][1] * m[1][3] * m[3][2] +
+            m[3][1] * m[1][2] * m[2][3] -
+            m[3][1] * m[1][3] * m[2][2],
+            // 0,1:
+           -m[0][1] * m[2][2] * m[3][3] +
+            m[0][1] * m[2][3] * m[3][2] +
+            m[2][1] * m[0][2] * m[3][3] -
+            m[2][1] * m[0][3] * m[3][2] -
+            m[3][1] * m[0][2] * m[2][3] +
+            m[3][1] * m[0][3] * m[2][2],
+            // 0,2:
+            m[0][1] * m[1][2] * m[3][3] -
+            m[0][1] * m[1][3] * m[3][2] -
+            m[1][1] * m[0][2] * m[3][3] +
+            m[1][1] * m[0][3] * m[3][2] +
+            m[3][1] * m[0][2] * m[1][3] -
+            m[3][1] * m[0][3] * m[1][2],
+            // 0,3:
+           -m[0][1] * m[1][2] * m[2][3] +
+            m[0][1] * m[1][3] * m[2][2] +
+            m[1][1] * m[0][2] * m[2][3] -
+            m[1][1] * m[0][3] * m[2][2] -
+            m[2][1] * m[0][2] * m[1][3] +
+            m[2][1] * m[0][3] * m[1][2],
+        ],
+        // row 1
+        [
+            // 1,0:
+           -m[1][0] * m[2][2] * m[3][3] +
+            m[1][0] * m[2][3] * m[3][2] +
+            m[2][0] * m[1][2] * m[3][3] -
+            m[2][0] * m[1][3] * m[3][2] -
+            m[3][0] * m[1][2] * m[2][3] +
+            m[3][0] * m[1][3] * m[2][2],
+            // 1,1:
+            m[0][0] * m[2][2] * m[3][3] -
+            m[0][0] * m[2][3] * m[3][2] -
+            m[2][0] * m[0][2] * m[3][3] +
+            m[2][0] * m[0][3] * m[3][2] +
+            m[3][0] * m[0][2] * m[2][3] -
+            m[3][0] * m[0][3] * m[2][2],
+            // 1,2:
+           -m[0][0] * m[1][2] * m[3][3] +
+            m[0][0] * m[1][3] * m[3][2] +
+            m[1][0] * m[0][2] * m[3][3] -
+            m[1][0] * m[0][3] * m[3][2] -
+            m[3][0] * m[0][2] * m[1][3] +
+            m[3][0] * m[0][3] * m[1][2],
+            // 1,3:
+            m[0][0] * m[1][2] * m[2][3] -
+            m[0][0] * m[1][3] * m[2][2] -
+            m[1][0] * m[0][2] * m[2][3] +
+            m[1][0] * m[0][3] * m[2][2] +
+            m[2][0] * m[0][2] * m[1][3] -
+            m[2][0] * m[0][3] * m[1][2],
+        ],
+        // row 2
+        [
+            // 2,0:
+            m[1][0] * m[2][1] * m[3][3] -
+            m[1][0] * m[2][3] * m[3][1] -
+            m[2][0] * m[1][1] * m[3][3] +
+            m[2][0] * m[1][3] * m[3][1] +
+            m[3][0] * m[1][1] * m[2][3] -
+            m[3][0] * m[1][3] * m[2][1],
+            // 2,1:
+           -m[0][0] * m[2][1] * m[3][3] +
+            m[0][0] * m[2][3] * m[3][1] +
+            m[2][0] * m[0][1] * m[3][3] -
+            m[2][0] * m[0][3] * m[3][1] -
+            m[3][0] * m[0][1] * m[2][3] +
+            m[3][0] * m[0][3] * m[2][1],
+            // 2,2:
+            m[0][0] * m[1][1] * m[3][3] -
+            m[0][0] * m[1][3] * m[3][1] -
+            m[1][0] * m[0][1] * m[3][3] +
+            m[1][0] * m[0][3] * m[3][1] +
+            m[3][0] * m[0][1] * m[1][3] -
+            m[3][0] * m[0][3] * m[1][1],
+            // 2,3:
+           -m[0][0] * m[1][1] * m[2][3] +
+            m[0][0] * m[1][3] * m[2][1] +
+            m[1][0] * m[0][1] * m[2][3] -
+            m[1][0] * m[0][3] * m[2][1] -
+            m[2][0] * m[0][1] * m[1][3] +
+            m[2][0] * m[0][3] * m[1][1],
+        ],
+        // row 3
+        [
+            // 3,0:
+           -m[1][0] * m[2][1] * m[3][2] +
+            m[1][0] * m[2][2] * m[3][1] +
+            m[2][0] * m[1][1] * m[3][2] -
+            m[2][0] * m[1][2] * m[3][1] -
+            m[3][0] * m[1][1] * m[2][2] +
+            m[3][0] * m[1][2] * m[2][1],
+            // 3,1:
+            m[0][0] * m[2][1] * m[3][2] -
+            m[0][0] * m[2][2] * m[3][1] -
+            m[2][0] * m[0][1] * m[3][2] +
+            m[2][0] * m[0][2] * m[3][1] +
+            m[3][0] * m[0][1] * m[2][2] -
+            m[3][0] * m[0][2] * m[2][1],
+            // 3,2:
+           -m[0][0] * m[1][1] * m[3][2] +
+            m[0][0] * m[1][2] * m[3][1] +
+            m[1][0] * m[0][1] * m[3][2] -
+            m[1][0] * m[0][2] * m[3][1] -
+            m[3][0] * m[0][1] * m[1][2] +
+            m[3][0] * m[0][2] * m[1][1],
+            // 3,3:
+            m[0][0] * m[1][1] * m[2][2] -
+            m[0][0] * m[1][2] * m[2][1] -
+            m[1][0] * m[0][1] * m[2][2] +
+            m[1][0] * m[0][2] * m[2][1] +
+            m[2][0] * m[0][1] * m[1][2] -
+            m[2][0] * m[0][2] * m[1][1],
+        ],
+    ];
+
+    let det = m[0][0] * inv[0][0] + m[0][1] * inv[1][0] + m[0][2] * inv[2][0] + m[0][3] * inv[3][0];
+    if det == 0. {
+        return None;
+    }
+
+    let det_inv = 1. / det;
+
+    for row in &mut inv {
+        for elem in row.iter_mut() {
+            *elem *= det_inv;
+        }
+    }
+
+    Some(Matrix4x4(inv))
+}
+
+pub fn simd_inv4x4(m: Matrix4x4) -> Option<Matrix4x4> {
+    let m = m.0;
+    let m_0 = f32x4::from_array(m[0]);
+    let m_1 = f32x4::from_array(m[1]);
+    let m_2 = f32x4::from_array(m[2]);
+    let m_3 = f32x4::from_array(m[3]);
+
+    const SHUFFLE01: [Which; 4] = [First(0), First(1), Second(0), Second(1)];
+    const SHUFFLE02: [Which; 4] = [First(0), First(2), Second(0), Second(2)];
+    const SHUFFLE13: [Which; 4] = [First(1), First(3), Second(1), Second(3)];
+    const SHUFFLE23: [Which; 4] = [First(2), First(3), Second(2), Second(3)];
+
+    let tmp = simd_swizzle!(m_0, m_1, SHUFFLE01);
+    let row1 = simd_swizzle!(m_2, m_3, SHUFFLE01);
+
+    let row0 = simd_swizzle!(tmp, row1, SHUFFLE02);
+    let row1 = simd_swizzle!(row1, tmp, SHUFFLE13);
+
+    let tmp = simd_swizzle!(m_0, m_1, SHUFFLE23);
+    let row3 = simd_swizzle!(m_2, m_3, SHUFFLE23);
+    let row2 = simd_swizzle!(tmp, row3, SHUFFLE02);
+    let row3 = simd_swizzle!(row3, tmp, SHUFFLE13);
+
+    let tmp = (row2 * row3).reverse().rotate_lanes_right::<2>();
+    let minor0 = row1 * tmp;
+    let minor1 = row0 * tmp;
+    let tmp = tmp.rotate_lanes_right::<2>();
+    let minor0 = (row1 * tmp) - minor0;
+    let minor1 = (row0 * tmp) - minor1;
+    let minor1 = minor1.rotate_lanes_right::<2>();
+
+    let tmp = (row1 * row2).reverse().rotate_lanes_right::<2>();
+    let minor0 = (row3 * tmp) + minor0;
+    let minor3 = row0 * tmp;
+    let tmp = tmp.rotate_lanes_right::<2>();
+
+    let minor0 = minor0 - row3 * tmp;
+    let minor3 = row0 * tmp - minor3;
+    let minor3 = minor3.rotate_lanes_right::<2>();
+
+    let tmp = (row3 * row1.rotate_lanes_right::<2>())
+        .reverse()
+        .rotate_lanes_right::<2>();
+    let row2 = row2.rotate_lanes_right::<2>();
+    let minor0 = row2 * tmp + minor0;
+    let minor2 = row0 * tmp;
+    let tmp = tmp.rotate_lanes_right::<2>();
+    let minor0 = minor0 - row2 * tmp;
+    let minor2 = row0 * tmp - minor2;
+    let minor2 = minor2.rotate_lanes_right::<2>();
+
+    let tmp = (row0 * row1).reverse().rotate_lanes_right::<2>();
+    let minor2 = minor2 + row3 * tmp;
+    let minor3 = row2 * tmp - minor3;
+    let tmp = tmp.rotate_lanes_right::<2>();
+    let minor2 = row3 * tmp - minor2;
+    let minor3 = minor3 - row2 * tmp;
+
+    let tmp = (row0 * row3).reverse().rotate_lanes_right::<2>();
+    let minor1 = minor1 - row2 * tmp;
+    let minor2 = row1 * tmp + minor2;
+    let tmp = tmp.rotate_lanes_right::<2>();
+    let minor1 = row2 * tmp + minor1;
+    let minor2 = minor2 - row1 * tmp;
+
+    let tmp = (row0 * row2).reverse().rotate_lanes_right::<2>();
+    let minor1 = row3 * tmp + minor1;
+    let minor3 = minor3 - row1 * tmp;
+    let tmp = tmp.rotate_lanes_right::<2>();
+    let minor1 = minor1 - row3 * tmp;
+    let minor3 = row1 * tmp + minor3;
+
+    let det = row0 * minor0;
+    let det = det.rotate_lanes_right::<2>() + det;
+    let det = det.reverse().rotate_lanes_right::<2>() + det;
+
+    if det.horizontal_sum() == 0. {
+        return None;
+    }
+    // calculate the reciprocal
+    let tmp = f32x4::splat(1.0) / det;
+    let det = tmp + tmp - det * tmp * tmp;
+
+    let res0 = minor0 * det;
+    let res1 = minor1 * det;
+    let res2 = minor2 * det;
+    let res3 = minor3 * det;
+
+    let mut m = m;
+
+    m[0] = res0.to_array();
+    m[1] = res1.to_array();
+    m[2] = res2.to_array();
+    m[3] = res3.to_array();
+
+    Some(Matrix4x4(m))
+}
+
+#[cfg(test)]
+#[rustfmt::skip]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test() {
+    let tests: &[(Matrix4x4, Option<Matrix4x4>)] = &[
+        // Identity:
+        (Matrix4x4([
+            [1., 0., 0., 0.],
+            [0., 1., 0., 0.],
+            [0., 0., 1., 0.],
+            [0., 0., 0., 1.],
+         ]),
+         Some(Matrix4x4([
+             [1., 0., 0., 0.],
+             [0., 1., 0., 0.],
+             [0., 0., 1., 0.],
+             [0., 0., 0., 1.],
+         ]))
+        ),
+        // None:
+        (Matrix4x4([
+            [1., 2., 3., 4.],
+            [12., 11., 10., 9.],
+            [5., 6., 7., 8.],
+            [16., 15., 14., 13.],
+        ]),
+         None
+        ),
+        // Other:
+        (Matrix4x4([
+            [1., 1., 1., 0.],
+            [0., 3., 1., 2.],
+            [2., 3., 1., 0.],
+            [1., 0., 2., 1.],
+        ]),
+         Some(Matrix4x4([
+             [-3., -0.5,   1.5,  1.0],
+             [ 1., 0.25, -0.25, -0.5],
+             [ 3., 0.25, -1.25, -0.5],
+             [-3., 0.0,    1.0,  1.0],
+         ]))
+        ),
+
+
+    ];
+
+        for &(input, output) in tests {
+            assert_eq!(scalar_inv4x4(input), output);
+            assert_eq!(simd_inv4x4(input), output);
+        }
+    }
+}
+
+fn main() {
+    // Empty main to make cargo happy
+}
diff --git a/library/portable-simd/crates/core_simd/examples/nbody.rs b/library/portable-simd/crates/core_simd/examples/nbody.rs
new file mode 100644 (file)
index 0000000..7795759
--- /dev/null
@@ -0,0 +1,193 @@
+#![cfg_attr(feature = "std", feature(portable_simd))]
+
+/// Benchmarks game nbody code
+/// Taken from the `packed_simd` crate
+/// Run this benchmark with `cargo test --example nbody`
+#[cfg(feature = "std")]
+mod nbody {
+    use core_simd::*;
+
+    use std::f64::consts::PI;
+    const SOLAR_MASS: f64 = 4.0 * PI * PI;
+    const DAYS_PER_YEAR: f64 = 365.24;
+
+    #[derive(Debug, Clone, Copy)]
+    struct Body {
+        pub x: f64x4,
+        pub v: f64x4,
+        pub mass: f64,
+    }
+
+    const N_BODIES: usize = 5;
+    const BODIES: [Body; N_BODIES] = [
+        // sun:
+        Body {
+            x: f64x4::from_array([0., 0., 0., 0.]),
+            v: f64x4::from_array([0., 0., 0., 0.]),
+            mass: SOLAR_MASS,
+        },
+        // jupiter:
+        Body {
+            x: f64x4::from_array([
+                4.84143144246472090e+00,
+                -1.16032004402742839e+00,
+                -1.03622044471123109e-01,
+                0.,
+            ]),
+            v: f64x4::from_array([
+                1.66007664274403694e-03 * DAYS_PER_YEAR,
+                7.69901118419740425e-03 * DAYS_PER_YEAR,
+                -6.90460016972063023e-05 * DAYS_PER_YEAR,
+                0.,
+            ]),
+            mass: 9.54791938424326609e-04 * SOLAR_MASS,
+        },
+        // saturn:
+        Body {
+            x: f64x4::from_array([
+                8.34336671824457987e+00,
+                4.12479856412430479e+00,
+                -4.03523417114321381e-01,
+                0.,
+            ]),
+            v: f64x4::from_array([
+                -2.76742510726862411e-03 * DAYS_PER_YEAR,
+                4.99852801234917238e-03 * DAYS_PER_YEAR,
+                2.30417297573763929e-05 * DAYS_PER_YEAR,
+                0.,
+            ]),
+            mass: 2.85885980666130812e-04 * SOLAR_MASS,
+        },
+        // uranus:
+        Body {
+            x: f64x4::from_array([
+                1.28943695621391310e+01,
+                -1.51111514016986312e+01,
+                -2.23307578892655734e-01,
+                0.,
+            ]),
+            v: f64x4::from_array([
+                2.96460137564761618e-03 * DAYS_PER_YEAR,
+                2.37847173959480950e-03 * DAYS_PER_YEAR,
+                -2.96589568540237556e-05 * DAYS_PER_YEAR,
+                0.,
+            ]),
+            mass: 4.36624404335156298e-05 * SOLAR_MASS,
+        },
+        // neptune:
+        Body {
+            x: f64x4::from_array([
+                1.53796971148509165e+01,
+                -2.59193146099879641e+01,
+                1.79258772950371181e-01,
+                0.,
+            ]),
+            v: f64x4::from_array([
+                2.68067772490389322e-03 * DAYS_PER_YEAR,
+                1.62824170038242295e-03 * DAYS_PER_YEAR,
+                -9.51592254519715870e-05 * DAYS_PER_YEAR,
+                0.,
+            ]),
+            mass: 5.15138902046611451e-05 * SOLAR_MASS,
+        },
+    ];
+
+    fn offset_momentum(bodies: &mut [Body; N_BODIES]) {
+        let (sun, rest) = bodies.split_at_mut(1);
+        let sun = &mut sun[0];
+        for body in rest {
+            let m_ratio = body.mass / SOLAR_MASS;
+            sun.v -= body.v * m_ratio;
+        }
+    }
+
+    fn energy(bodies: &[Body; N_BODIES]) -> f64 {
+        let mut e = 0.;
+        for i in 0..N_BODIES {
+            let bi = &bodies[i];
+            e += bi.mass * (bi.v * bi.v).horizontal_sum() * 0.5;
+            for bj in bodies.iter().take(N_BODIES).skip(i + 1) {
+                let dx = bi.x - bj.x;
+                e -= bi.mass * bj.mass / (dx * dx).horizontal_sum().sqrt()
+            }
+        }
+        e
+    }
+
+    fn advance(bodies: &mut [Body; N_BODIES], dt: f64) {
+        const N: usize = N_BODIES * (N_BODIES - 1) / 2;
+
+        // compute distance between bodies:
+        let mut r = [f64x4::splat(0.); N];
+        {
+            let mut i = 0;
+            for j in 0..N_BODIES {
+                for k in j + 1..N_BODIES {
+                    r[i] = bodies[j].x - bodies[k].x;
+                    i += 1;
+                }
+            }
+        }
+
+        let mut mag = [0.0; N];
+        for i in (0..N).step_by(2) {
+            let d2s = f64x2::from_array([
+                (r[i] * r[i]).horizontal_sum(),
+                (r[i + 1] * r[i + 1]).horizontal_sum(),
+            ]);
+            let dmags = f64x2::splat(dt) / (d2s * d2s.sqrt());
+            mag[i] = dmags[0];
+            mag[i + 1] = dmags[1];
+        }
+
+        let mut i = 0;
+        for j in 0..N_BODIES {
+            for k in j + 1..N_BODIES {
+                let f = r[i] * mag[i];
+                bodies[j].v -= f * bodies[k].mass;
+                bodies[k].v += f * bodies[j].mass;
+                i += 1
+            }
+        }
+        for body in bodies {
+            body.x += dt * body.v
+        }
+    }
+
+    pub fn run(n: usize) -> (f64, f64) {
+        let mut bodies = BODIES;
+        offset_momentum(&mut bodies);
+        let energy_before = energy(&bodies);
+        for _ in 0..n {
+            advance(&mut bodies, 0.01);
+        }
+        let energy_after = energy(&bodies);
+
+        (energy_before, energy_after)
+    }
+}
+
+#[cfg(feature = "std")]
+#[cfg(test)]
+mod tests {
+    // Good enough for demonstration purposes, not going for strictness here.
+    fn approx_eq_f64(a: f64, b: f64) -> bool {
+        (a - b).abs() < 0.00001
+    }
+    #[test]
+    fn test() {
+        const OUTPUT: [f64; 2] = [-0.169075164, -0.169087605];
+        let (energy_before, energy_after) = super::nbody::run(1000);
+        assert!(approx_eq_f64(energy_before, OUTPUT[0]));
+        assert!(approx_eq_f64(energy_after, OUTPUT[1]));
+    }
+}
+
+fn main() {
+    #[cfg(feature = "std")]
+    {
+        let (energy_before, energy_after) = nbody::run(1000);
+        println!("Energy before: {}", energy_before);
+        println!("Energy after:  {}", energy_after);
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/src/comparisons.rs b/library/portable-simd/crates/core_simd/src/comparisons.rs
new file mode 100644 (file)
index 0000000..8c51bac
--- /dev/null
@@ -0,0 +1,50 @@
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Mask, Simd, SimdElement, SupportedLaneCount};
+
+impl<T, const LANES: usize> Simd<T, LANES>
+where
+    T: SimdElement + PartialEq,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    /// Test if each lane is equal to the corresponding lane in `other`.
+    #[inline]
+    pub fn lanes_eq(self, other: Self) -> Mask<T::Mask, LANES> {
+        unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) }
+    }
+
+    /// Test if each lane is not equal to the corresponding lane in `other`.
+    #[inline]
+    pub fn lanes_ne(self, other: Self) -> Mask<T::Mask, LANES> {
+        unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) }
+    }
+}
+
+impl<T, const LANES: usize> Simd<T, LANES>
+where
+    T: SimdElement + PartialOrd,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    /// Test if each lane is less than the corresponding lane in `other`.
+    #[inline]
+    pub fn lanes_lt(self, other: Self) -> Mask<T::Mask, LANES> {
+        unsafe { Mask::from_int_unchecked(intrinsics::simd_lt(self, other)) }
+    }
+
+    /// Test if each lane is greater than the corresponding lane in `other`.
+    #[inline]
+    pub fn lanes_gt(self, other: Self) -> Mask<T::Mask, LANES> {
+        unsafe { Mask::from_int_unchecked(intrinsics::simd_gt(self, other)) }
+    }
+
+    /// Test if each lane is less than or equal to the corresponding lane in `other`.
+    #[inline]
+    pub fn lanes_le(self, other: Self) -> Mask<T::Mask, LANES> {
+        unsafe { Mask::from_int_unchecked(intrinsics::simd_le(self, other)) }
+    }
+
+    /// Test if each lane is greater than or equal to the corresponding lane in `other`.
+    #[inline]
+    pub fn lanes_ge(self, other: Self) -> Mask<T::Mask, LANES> {
+        unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) }
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/src/core_simd_docs.md b/library/portable-simd/crates/core_simd/src/core_simd_docs.md
new file mode 100644 (file)
index 0000000..15e8ed0
--- /dev/null
@@ -0,0 +1,4 @@
+Portable SIMD module.
+
+This module offers a portable abstraction for SIMD operations
+that is not bound to any particular hardware architecture.
diff --git a/library/portable-simd/crates/core_simd/src/fmt.rs b/library/portable-simd/crates/core_simd/src/fmt.rs
new file mode 100644 (file)
index 0000000..dbd9839
--- /dev/null
@@ -0,0 +1,39 @@
+use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
+use core::fmt;
+
+macro_rules! impl_fmt_trait {
+    { $($trait:ident,)* } => {
+        $(
+            impl<T, const LANES: usize> fmt::$trait for Simd<T, LANES>
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+                T: SimdElement + fmt::$trait,
+            {
+                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    #[repr(transparent)]
+                    struct Wrapper<'a, T: fmt::$trait>(&'a T);
+
+                    impl<T: fmt::$trait> fmt::Debug for Wrapper<'_, T> {
+                        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                            self.0.fmt(f)
+                        }
+                    }
+
+                    f.debug_list()
+                        .entries(self.as_array().iter().map(|x| Wrapper(x)))
+                        .finish()
+                }
+            }
+        )*
+    }
+}
+
+impl_fmt_trait! {
+    Debug,
+    Binary,
+    LowerExp,
+    UpperExp,
+    Octal,
+    LowerHex,
+    UpperHex,
+}
diff --git a/library/portable-simd/crates/core_simd/src/intrinsics.rs b/library/portable-simd/crates/core_simd/src/intrinsics.rs
new file mode 100644 (file)
index 0000000..6a6d26d
--- /dev/null
@@ -0,0 +1,115 @@
+//! This module contains the LLVM intrinsics bindings that provide the functionality for this
+//! crate.
+//!
+//! The LLVM assembly language is documented here: <https://llvm.org/docs/LangRef.html>
+
+/// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are
+/// simply lowered to the matching LLVM instructions by the compiler.  The associated instruction
+/// is documented alongside each intrinsic.
+extern "platform-intrinsic" {
+    /// add/fadd
+    pub(crate) fn simd_add<T>(x: T, y: T) -> T;
+
+    /// sub/fsub
+    pub(crate) fn simd_sub<T>(x: T, y: T) -> T;
+
+    /// mul/fmul
+    pub(crate) fn simd_mul<T>(x: T, y: T) -> T;
+
+    /// udiv/sdiv/fdiv
+    pub(crate) fn simd_div<T>(x: T, y: T) -> T;
+
+    /// urem/srem/frem
+    pub(crate) fn simd_rem<T>(x: T, y: T) -> T;
+
+    /// shl
+    pub(crate) fn simd_shl<T>(x: T, y: T) -> T;
+
+    /// lshr/ashr
+    pub(crate) fn simd_shr<T>(x: T, y: T) -> T;
+
+    /// and
+    pub(crate) fn simd_and<T>(x: T, y: T) -> T;
+
+    /// or
+    pub(crate) fn simd_or<T>(x: T, y: T) -> T;
+
+    /// xor
+    pub(crate) fn simd_xor<T>(x: T, y: T) -> T;
+
+    /// fptoui/fptosi/uitofp/sitofp
+    pub(crate) fn simd_cast<T, U>(x: T) -> U;
+
+    /// neg/fneg
+    pub(crate) fn simd_neg<T>(x: T) -> T;
+
+    /// fabs
+    pub(crate) fn simd_fabs<T>(x: T) -> T;
+
+    pub(crate) fn simd_eq<T, U>(x: T, y: T) -> U;
+    pub(crate) fn simd_ne<T, U>(x: T, y: T) -> U;
+    pub(crate) fn simd_lt<T, U>(x: T, y: T) -> U;
+    pub(crate) fn simd_le<T, U>(x: T, y: T) -> U;
+    pub(crate) fn simd_gt<T, U>(x: T, y: T) -> U;
+    pub(crate) fn simd_ge<T, U>(x: T, y: T) -> U;
+
+    // shufflevector
+    pub(crate) fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
+
+    pub(crate) fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
+    pub(crate) fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
+
+    // {s,u}add.sat
+    pub(crate) fn simd_saturating_add<T>(x: T, y: T) -> T;
+
+    // {s,u}sub.sat
+    pub(crate) fn simd_saturating_sub<T>(x: T, y: T) -> T;
+
+    // reductions
+    pub(crate) fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
+    pub(crate) fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
+    #[allow(unused)]
+    pub(crate) fn simd_reduce_all<T>(x: T) -> bool;
+    #[allow(unused)]
+    pub(crate) fn simd_reduce_any<T>(x: T) -> bool;
+    pub(crate) fn simd_reduce_max<T, U>(x: T) -> U;
+    pub(crate) fn simd_reduce_min<T, U>(x: T) -> U;
+    pub(crate) fn simd_reduce_and<T, U>(x: T) -> U;
+    pub(crate) fn simd_reduce_or<T, U>(x: T) -> U;
+    pub(crate) fn simd_reduce_xor<T, U>(x: T) -> U;
+
+    // truncate integer vector to bitmask
+    #[allow(unused)]
+    pub(crate) fn simd_bitmask<T, U>(x: T) -> U;
+
+    // select
+    pub(crate) fn simd_select<M, T>(m: M, a: T, b: T) -> T;
+    #[allow(unused)]
+    pub(crate) fn simd_select_bitmask<M, T>(m: M, a: T, b: T) -> T;
+}
+
+#[cfg(feature = "std")]
+mod std {
+    extern "platform-intrinsic" {
+        // ceil
+        pub(crate) fn simd_ceil<T>(x: T) -> T;
+
+        // floor
+        pub(crate) fn simd_floor<T>(x: T) -> T;
+
+        // round
+        pub(crate) fn simd_round<T>(x: T) -> T;
+
+        // trunc
+        pub(crate) fn simd_trunc<T>(x: T) -> T;
+
+        // fsqrt
+        pub(crate) fn simd_fsqrt<T>(x: T) -> T;
+
+        // fma
+        pub(crate) fn simd_fma<T>(x: T, y: T, z: T) -> T;
+    }
+}
+
+#[cfg(feature = "std")]
+pub(crate) use crate::simd::intrinsics::std::*;
diff --git a/library/portable-simd/crates/core_simd/src/iter.rs b/library/portable-simd/crates/core_simd/src/iter.rs
new file mode 100644 (file)
index 0000000..3275b4d
--- /dev/null
@@ -0,0 +1,58 @@
+use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+use core::{
+    iter::{Product, Sum},
+    ops::{Add, Mul},
+};
+
+macro_rules! impl_traits {
+    { $type:ty } => {
+        impl<const LANES: usize> Sum<Self> for Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
+                iter.fold(Simd::splat(0 as $type), Add::add)
+            }
+        }
+
+        impl<const LANES: usize> Product<Self> for Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
+                iter.fold(Simd::splat(1 as $type), Mul::mul)
+            }
+        }
+
+        impl<'a, const LANES: usize> Sum<&'a Self> for Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
+                iter.fold(Simd::splat(0 as $type), Add::add)
+            }
+        }
+
+        impl<'a, const LANES: usize> Product<&'a Self> for Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
+                iter.fold(Simd::splat(1 as $type), Mul::mul)
+            }
+        }
+    }
+}
+
+impl_traits! { f32 }
+impl_traits! { f64 }
+impl_traits! { u8 }
+impl_traits! { u16 }
+impl_traits! { u32 }
+impl_traits! { u64 }
+impl_traits! { usize }
+impl_traits! { i8 }
+impl_traits! { i16 }
+impl_traits! { i32 }
+impl_traits! { i64 }
+impl_traits! { isize }
diff --git a/library/portable-simd/crates/core_simd/src/lane_count.rs b/library/portable-simd/crates/core_simd/src/lane_count.rs
new file mode 100644 (file)
index 0000000..b017e7d
--- /dev/null
@@ -0,0 +1,48 @@
+mod sealed {
+    pub trait Sealed {}
+}
+use sealed::Sealed;
+
+/// A type representing a vector lane count.
+pub struct LaneCount<const LANES: usize>;
+
+impl<const LANES: usize> LaneCount<LANES> {
+    /// The number of bytes in a bitmask with this many lanes.
+    pub const BITMASK_LEN: usize = (LANES + 7) / 8;
+}
+
+/// Helper trait for vector lane counts.
+pub trait SupportedLaneCount: Sealed {
+    #[doc(hidden)]
+    type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>;
+
+    #[doc(hidden)]
+    type IntBitMask;
+}
+
+impl<const LANES: usize> Sealed for LaneCount<LANES> {}
+
+impl SupportedLaneCount for LaneCount<1> {
+    type BitMask = [u8; 1];
+    type IntBitMask = u8;
+}
+impl SupportedLaneCount for LaneCount<2> {
+    type BitMask = [u8; 1];
+    type IntBitMask = u8;
+}
+impl SupportedLaneCount for LaneCount<4> {
+    type BitMask = [u8; 1];
+    type IntBitMask = u8;
+}
+impl SupportedLaneCount for LaneCount<8> {
+    type BitMask = [u8; 1];
+    type IntBitMask = u8;
+}
+impl SupportedLaneCount for LaneCount<16> {
+    type BitMask = [u8; 2];
+    type IntBitMask = u16;
+}
+impl SupportedLaneCount for LaneCount<32> {
+    type BitMask = [u8; 4];
+    type IntBitMask = u32;
+}
diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs
new file mode 100644 (file)
index 0000000..960a664
--- /dev/null
@@ -0,0 +1,21 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+#![feature(
+    const_fn_trait_bound,
+    decl_macro,
+    platform_intrinsics,
+    repr_simd,
+    simd_ffi,
+    staged_api,
+    stdsimd
+)]
+#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))]
+#![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))]
+#![warn(missing_docs)]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![unstable(feature = "portable_simd", issue = "86656")]
+//! Portable SIMD module.
+
+#[path = "mod.rs"]
+mod core_simd;
+pub use self::core_simd::simd;
+pub use simd::*;
diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs
new file mode 100644 (file)
index 0000000..d460da0
--- /dev/null
@@ -0,0 +1,545 @@
+//! Types and traits associated with masking lanes of vectors.
+//! Types representing
+#![allow(non_camel_case_types)]
+
+#[cfg_attr(
+    not(all(target_arch = "x86_64", target_feature = "avx512f")),
+    path = "masks/full_masks.rs"
+)]
+#[cfg_attr(
+    all(target_arch = "x86_64", target_feature = "avx512f"),
+    path = "masks/bitmask.rs"
+)]
+mod mask_impl;
+
+use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
+use core::cmp::Ordering;
+use core::fmt;
+
+mod sealed {
+    use super::*;
+
+    /// Not only does this seal the `MaskElement` trait, but these functions prevent other traits
+    /// from bleeding into the parent bounds.
+    ///
+    /// For example, `eq` could be provided by requiring `MaskElement: PartialEq`, but that would
+    /// prevent us from ever removing that bound, or from implementing `MaskElement` on
+    /// non-`PartialEq` types in the future.
+    pub trait Sealed {
+        fn valid<const LANES: usize>(values: Simd<Self, LANES>) -> bool
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+            Self: SimdElement;
+
+        fn eq(self, other: Self) -> bool;
+
+        const TRUE: Self;
+
+        const FALSE: Self;
+    }
+}
+use sealed::Sealed;
+
+/// Marker trait for types that may be used as SIMD mask elements.
+pub unsafe trait MaskElement: SimdElement + Sealed {}
+
+macro_rules! impl_element {
+    { $ty:ty } => {
+        impl Sealed for $ty {
+            fn valid<const LANES: usize>(value: Simd<Self, LANES>) -> bool
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                (value.lanes_eq(Simd::splat(0)) | value.lanes_eq(Simd::splat(-1))).all()
+            }
+
+            fn eq(self, other: Self) -> bool { self == other }
+
+            const TRUE: Self = -1;
+            const FALSE: Self = 0;
+        }
+
+        unsafe impl MaskElement for $ty {}
+    }
+}
+
+impl_element! { i8 }
+impl_element! { i16 }
+impl_element! { i32 }
+impl_element! { i64 }
+impl_element! { isize }
+
+/// A SIMD vector mask for `LANES` elements of width specified by `Element`.
+///
+/// The layout of this type is unspecified.
+#[repr(transparent)]
+pub struct Mask<T, const LANES: usize>(mask_impl::Mask<T, LANES>)
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount;
+
+impl<T, const LANES: usize> Copy for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Clone for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<T, const LANES: usize> Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    /// Construct a mask by setting all lanes to the given value.
+    pub fn splat(value: bool) -> Self {
+        Self(mask_impl::Mask::splat(value))
+    }
+
+    /// Converts an array to a SIMD vector.
+    pub fn from_array(array: [bool; LANES]) -> Self {
+        let mut vector = Self::splat(false);
+        for (i, v) in array.iter().enumerate() {
+            vector.set(i, *v);
+        }
+        vector
+    }
+
+    /// Converts a SIMD vector to an array.
+    pub fn to_array(self) -> [bool; LANES] {
+        let mut array = [false; LANES];
+        for (i, v) in array.iter_mut().enumerate() {
+            *v = self.test(i);
+        }
+        array
+    }
+
+    /// Converts a vector of integers to a mask, where 0 represents `false` and -1
+    /// represents `true`.
+    ///
+    /// # Safety
+    /// All lanes must be either 0 or -1.
+    #[inline]
+    pub unsafe fn from_int_unchecked(value: Simd<T, LANES>) -> Self {
+        unsafe { Self(mask_impl::Mask::from_int_unchecked(value)) }
+    }
+
+    /// Converts a vector of integers to a mask, where 0 represents `false` and -1
+    /// represents `true`.
+    ///
+    /// # Panics
+    /// Panics if any lane is not 0 or -1.
+    #[inline]
+    pub fn from_int(value: Simd<T, LANES>) -> Self {
+        assert!(T::valid(value), "all values must be either 0 or -1",);
+        unsafe { Self::from_int_unchecked(value) }
+    }
+
+    /// Converts the mask to a vector of integers, where 0 represents `false` and -1
+    /// represents `true`.
+    #[inline]
+    pub fn to_int(self) -> Simd<T, LANES> {
+        self.0.to_int()
+    }
+
+    /// Tests the value of the specified lane.
+    ///
+    /// # Safety
+    /// `lane` must be less than `LANES`.
+    #[inline]
+    pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
+        unsafe { self.0.test_unchecked(lane) }
+    }
+
+    /// Tests the value of the specified lane.
+    ///
+    /// # Panics
+    /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
+    #[inline]
+    pub fn test(&self, lane: usize) -> bool {
+        assert!(lane < LANES, "lane index out of range");
+        unsafe { self.test_unchecked(lane) }
+    }
+
+    /// Sets the value of the specified lane.
+    ///
+    /// # Safety
+    /// `lane` must be less than `LANES`.
+    #[inline]
+    pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
+        unsafe {
+            self.0.set_unchecked(lane, value);
+        }
+    }
+
+    /// Sets the value of the specified lane.
+    ///
+    /// # Panics
+    /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
+    #[inline]
+    pub fn set(&mut self, lane: usize, value: bool) {
+        assert!(lane < LANES, "lane index out of range");
+        unsafe {
+            self.set_unchecked(lane, value);
+        }
+    }
+
+    /// Convert this mask to a bitmask, with one bit set per lane.
+    #[cfg(feature = "generic_const_exprs")]
+    pub fn to_bitmask(self) -> [u8; LaneCount::<LANES>::BITMASK_LEN] {
+        self.0.to_bitmask()
+    }
+
+    /// Convert a bitmask to a mask.
+    #[cfg(feature = "generic_const_exprs")]
+    pub fn from_bitmask(bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN]) -> Self {
+        Self(mask_impl::Mask::from_bitmask(bitmask))
+    }
+
+    /// Returns true if any lane is set, or false otherwise.
+    #[inline]
+    pub fn any(self) -> bool {
+        self.0.any()
+    }
+
+    /// Returns true if all lanes are set, or false otherwise.
+    #[inline]
+    pub fn all(self) -> bool {
+        self.0.all()
+    }
+}
+
+// vector/array conversion
+impl<T, const LANES: usize> From<[bool; LANES]> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn from(array: [bool; LANES]) -> Self {
+        Self::from_array(array)
+    }
+}
+
+impl<T, const LANES: usize> From<Mask<T, LANES>> for [bool; LANES]
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn from(vector: Mask<T, LANES>) -> Self {
+        vector.to_array()
+    }
+}
+
+impl<T, const LANES: usize> Default for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn default() -> Self {
+        Self::splat(false)
+    }
+}
+
+impl<T, const LANES: usize> PartialEq for Mask<T, LANES>
+where
+    T: MaskElement + PartialEq,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl<T, const LANES: usize> PartialOrd for Mask<T, LANES>
+where
+    T: MaskElement + PartialOrd,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.0.partial_cmp(&other.0)
+    }
+}
+
+impl<T, const LANES: usize> fmt::Debug for Mask<T, LANES>
+where
+    T: MaskElement + fmt::Debug,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list()
+            .entries((0..LANES).map(|lane| self.test(lane)))
+            .finish()
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitAnd for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self {
+        Self(self.0 & rhs.0)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitAnd<bool> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: bool) -> Self {
+        self & Self::splat(rhs)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitAnd<Mask<T, LANES>> for bool
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Mask<T, LANES>;
+    #[inline]
+    fn bitand(self, rhs: Mask<T, LANES>) -> Mask<T, LANES> {
+        Mask::splat(self) & rhs
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitOr for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self {
+        Self(self.0 | rhs.0)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitOr<bool> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: bool) -> Self {
+        self | Self::splat(rhs)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitOr<Mask<T, LANES>> for bool
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Mask<T, LANES>;
+    #[inline]
+    fn bitor(self, rhs: Mask<T, LANES>) -> Mask<T, LANES> {
+        Mask::splat(self) | rhs
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitXor for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self::Output {
+        Self(self.0 ^ rhs.0)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitXor<bool> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: bool) -> Self::Output {
+        self ^ Self::splat(rhs)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitXor<Mask<T, LANES>> for bool
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Mask<T, LANES>;
+    #[inline]
+    fn bitxor(self, rhs: Mask<T, LANES>) -> Self::Output {
+        Mask::splat(self) ^ rhs
+    }
+}
+
+impl<T, const LANES: usize> core::ops::Not for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Mask<T, LANES>;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self(!self.0)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitAndAssign for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn bitand_assign(&mut self, rhs: Self) {
+        self.0 = self.0 & rhs.0;
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitAndAssign<bool> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn bitand_assign(&mut self, rhs: bool) {
+        *self &= Self::splat(rhs);
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitOrAssign for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn bitor_assign(&mut self, rhs: Self) {
+        self.0 = self.0 | rhs.0;
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitOrAssign<bool> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn bitor_assign(&mut self, rhs: bool) {
+        *self |= Self::splat(rhs);
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitXorAssign for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn bitxor_assign(&mut self, rhs: Self) {
+        self.0 = self.0 ^ rhs.0;
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitXorAssign<bool> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn bitxor_assign(&mut self, rhs: bool) {
+        *self ^= Self::splat(rhs);
+    }
+}
+
+/// Vector of eight 8-bit masks
+pub type mask8x8 = Mask<i8, 8>;
+
+/// Vector of 16 8-bit masks
+pub type mask8x16 = Mask<i8, 16>;
+
+/// Vector of 32 8-bit masks
+pub type mask8x32 = Mask<i8, 32>;
+
+/// Vector of 16 8-bit masks
+pub type mask8x64 = Mask<i8, 64>;
+
+/// Vector of four 16-bit masks
+pub type mask16x4 = Mask<i16, 4>;
+
+/// Vector of eight 16-bit masks
+pub type mask16x8 = Mask<i16, 8>;
+
+/// Vector of 16 16-bit masks
+pub type mask16x16 = Mask<i16, 16>;
+
+/// Vector of 32 16-bit masks
+pub type mask16x32 = Mask<i32, 32>;
+
+/// Vector of two 32-bit masks
+pub type mask32x2 = Mask<i32, 2>;
+
+/// Vector of four 32-bit masks
+pub type mask32x4 = Mask<i32, 4>;
+
+/// Vector of eight 32-bit masks
+pub type mask32x8 = Mask<i32, 8>;
+
+/// Vector of 16 32-bit masks
+pub type mask32x16 = Mask<i32, 16>;
+
+/// Vector of two 64-bit masks
+pub type mask64x2 = Mask<i64, 2>;
+
+/// Vector of four 64-bit masks
+pub type mask64x4 = Mask<i64, 4>;
+
+/// Vector of eight 64-bit masks
+pub type mask64x8 = Mask<i64, 8>;
+
+/// Vector of two pointer-width masks
+pub type masksizex2 = Mask<isize, 2>;
+
+/// Vector of four pointer-width masks
+pub type masksizex4 = Mask<isize, 4>;
+
+/// Vector of eight pointer-width masks
+pub type masksizex8 = Mask<isize, 8>;
+
+macro_rules! impl_from {
+    { $from:ty  => $($to:ty),* } => {
+        $(
+        impl<const LANES: usize> From<Mask<$from, LANES>> for Mask<$to, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            fn from(value: Mask<$from, LANES>) -> Self {
+                Self(value.0.convert())
+            }
+        }
+        )*
+    }
+}
+impl_from! { i8 => i16, i32, i64, isize }
+impl_from! { i16 => i32, i64, isize, i8 }
+impl_from! { i32 => i64, isize, i8, i16 }
+impl_from! { i64 => isize, i8, i16, i32 }
+impl_from! { isize => i8, i16, i32, i64 }
diff --git a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs
new file mode 100644 (file)
index 0000000..2689e1a
--- /dev/null
@@ -0,0 +1,220 @@
+use super::MaskElement;
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+use core::marker::PhantomData;
+
+/// A mask where each lane is represented by a single bit.
+#[repr(transparent)]
+pub struct Mask<T, const LANES: usize>(
+    <LaneCount<LANES> as SupportedLaneCount>::BitMask,
+    PhantomData<T>,
+)
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount;
+
+impl<T, const LANES: usize> Copy for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Clone for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<T, const LANES: usize> PartialEq for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn eq(&self, other: &Self) -> bool {
+        self.0.as_ref() == other.0.as_ref()
+    }
+}
+
+impl<T, const LANES: usize> PartialOrd for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+        self.0.as_ref().partial_cmp(other.0.as_ref())
+    }
+}
+
+impl<T, const LANES: usize> Eq for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Ord for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+        self.0.as_ref().cmp(other.0.as_ref())
+    }
+}
+
+impl<T, const LANES: usize> Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    pub fn splat(value: bool) -> Self {
+        let mut mask = <LaneCount<LANES> as SupportedLaneCount>::BitMask::default();
+        if value {
+            mask.as_mut().fill(u8::MAX)
+        } else {
+            mask.as_mut().fill(u8::MIN)
+        }
+        if LANES % 8 > 0 {
+            *mask.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - LANES % 8);
+        }
+        Self(mask, PhantomData)
+    }
+
+    #[inline]
+    pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
+        (self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0
+    }
+
+    #[inline]
+    pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
+        unsafe {
+            self.0.as_mut()[lane / 8] ^= ((value ^ self.test_unchecked(lane)) as u8) << (lane % 8)
+        }
+    }
+
+    #[inline]
+    pub fn to_int(self) -> Simd<T, LANES> {
+        unsafe {
+            let mask: <LaneCount<LANES> as SupportedLaneCount>::IntBitMask =
+                core::mem::transmute_copy(&self);
+            intrinsics::simd_select_bitmask(mask, Simd::splat(T::TRUE), Simd::splat(T::FALSE))
+        }
+    }
+
+    #[inline]
+    pub unsafe fn from_int_unchecked(value: Simd<T, LANES>) -> Self {
+        // TODO remove the transmute when rustc is more flexible
+        assert_eq!(
+            core::mem::size_of::<<LaneCount::<LANES> as SupportedLaneCount>::BitMask>(),
+            core::mem::size_of::<<LaneCount::<LANES> as SupportedLaneCount>::IntBitMask>(),
+        );
+        unsafe {
+            let mask: <LaneCount<LANES> as SupportedLaneCount>::IntBitMask =
+                intrinsics::simd_bitmask(value);
+            Self(core::mem::transmute_copy(&mask), PhantomData)
+        }
+    }
+
+    #[cfg(feature = "generic_const_exprs")]
+    #[inline]
+    pub fn to_bitmask(self) -> [u8; LaneCount::<LANES>::BITMASK_LEN] {
+        // Safety: these are the same type and we are laundering the generic
+        unsafe { core::mem::transmute_copy(&self.0) }
+    }
+
+    #[cfg(feature = "generic_const_exprs")]
+    #[inline]
+    pub fn from_bitmask(bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN]) -> Self {
+        // Safety: these are the same type and we are laundering the generic
+        Self(unsafe { core::mem::transmute_copy(&bitmask) }, PhantomData)
+    }
+
+    #[inline]
+    pub fn convert<U>(self) -> Mask<U, LANES>
+    where
+        U: MaskElement,
+    {
+        unsafe { core::mem::transmute_copy(&self) }
+    }
+
+    #[inline]
+    pub fn any(self) -> bool {
+        self != Self::splat(false)
+    }
+
+    #[inline]
+    pub fn all(self) -> bool {
+        self == Self::splat(true)
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitAnd for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+    <LaneCount<LANES> as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>,
+{
+    type Output = Self;
+    #[inline]
+    fn bitand(mut self, rhs: Self) -> Self {
+        for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) {
+            *l &= r;
+        }
+        self
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitOr for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+    <LaneCount<LANES> as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>,
+{
+    type Output = Self;
+    #[inline]
+    fn bitor(mut self, rhs: Self) -> Self {
+        for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) {
+            *l |= r;
+        }
+        self
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitXor for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitxor(mut self, rhs: Self) -> Self::Output {
+        for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) {
+            *l ^= r;
+        }
+        self
+    }
+}
+
+impl<T, const LANES: usize> core::ops::Not for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn not(mut self) -> Self::Output {
+        for x in self.0.as_mut() {
+            *x = !*x;
+        }
+        if LANES % 8 > 0 {
+            *self.0.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - LANES % 8);
+        }
+        self
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs
new file mode 100644 (file)
index 0000000..dd981ce
--- /dev/null
@@ -0,0 +1,228 @@
+//! Masks that take up full SIMD vector registers.
+
+use super::MaskElement;
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+
+#[repr(transparent)]
+pub struct Mask<T, const LANES: usize>(Simd<T, LANES>)
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount;
+
+impl<T, const LANES: usize> Copy for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Clone for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<T, const LANES: usize> PartialEq for Mask<T, LANES>
+where
+    T: MaskElement + PartialEq,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn eq(&self, other: &Self) -> bool {
+        self.0.eq(&other.0)
+    }
+}
+
+impl<T, const LANES: usize> PartialOrd for Mask<T, LANES>
+where
+    T: MaskElement + PartialOrd,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+        self.0.partial_cmp(&other.0)
+    }
+}
+
+impl<T, const LANES: usize> Eq for Mask<T, LANES>
+where
+    T: MaskElement + Eq,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Ord for Mask<T, LANES>
+where
+    T: MaskElement + Ord,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+        self.0.cmp(&other.0)
+    }
+}
+
+impl<T, const LANES: usize> Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    pub fn splat(value: bool) -> Self {
+        Self(Simd::splat(if value { T::TRUE } else { T::FALSE }))
+    }
+
+    #[inline]
+    pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
+        T::eq(self.0[lane], T::TRUE)
+    }
+
+    #[inline]
+    pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
+        self.0[lane] = if value { T::TRUE } else { T::FALSE }
+    }
+
+    #[inline]
+    pub fn to_int(self) -> Simd<T, LANES> {
+        self.0
+    }
+
+    #[inline]
+    pub unsafe fn from_int_unchecked(value: Simd<T, LANES>) -> Self {
+        Self(value)
+    }
+
+    #[inline]
+    pub fn convert<U>(self) -> Mask<U, LANES>
+    where
+        U: MaskElement,
+    {
+        unsafe { Mask(intrinsics::simd_cast(self.0)) }
+    }
+
+    #[cfg(feature = "generic_const_exprs")]
+    #[inline]
+    pub fn to_bitmask(self) -> [u8; LaneCount::<LANES>::BITMASK_LEN] {
+        unsafe {
+            // TODO remove the transmute when rustc can use arrays of u8 as bitmasks
+            assert_eq!(
+                core::mem::size_of::<<LaneCount::<LANES> as SupportedLaneCount>::IntBitMask>(),
+                LaneCount::<LANES>::BITMASK_LEN,
+            );
+            let bitmask: <LaneCount<LANES> as SupportedLaneCount>::IntBitMask =
+                intrinsics::simd_bitmask(self.0);
+            let mut bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN] =
+                core::mem::transmute_copy(&bitmask);
+
+            // There is a bug where LLVM appears to implement this operation with the wrong
+            // bit order.
+            // TODO fix this in a better way
+            if cfg!(target_endian = "big") {
+                for x in bitmask.as_mut() {
+                    *x = x.reverse_bits();
+                }
+            }
+
+            bitmask
+        }
+    }
+
+    #[cfg(feature = "generic_const_exprs")]
+    #[inline]
+    pub fn from_bitmask(mut bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN]) -> Self {
+        unsafe {
+            // There is a bug where LLVM appears to implement this operation with the wrong
+            // bit order.
+            // TODO fix this in a better way
+            if cfg!(target_endian = "big") {
+                for x in bitmask.as_mut() {
+                    *x = x.reverse_bits();
+                }
+            }
+
+            // TODO remove the transmute when rustc can use arrays of u8 as bitmasks
+            assert_eq!(
+                core::mem::size_of::<<LaneCount::<LANES> as SupportedLaneCount>::IntBitMask>(),
+                LaneCount::<LANES>::BITMASK_LEN,
+            );
+            let bitmask: <LaneCount<LANES> as SupportedLaneCount>::IntBitMask =
+                core::mem::transmute_copy(&bitmask);
+
+            Self::from_int_unchecked(intrinsics::simd_select_bitmask(
+                bitmask,
+                Self::splat(true).to_int(),
+                Self::splat(false).to_int(),
+            ))
+        }
+    }
+
+    #[inline]
+    pub fn any(self) -> bool {
+        unsafe { intrinsics::simd_reduce_any(self.to_int()) }
+    }
+
+    #[inline]
+    pub fn all(self) -> bool {
+        unsafe { intrinsics::simd_reduce_all(self.to_int()) }
+    }
+}
+
+impl<T, const LANES: usize> core::convert::From<Mask<T, LANES>> for Simd<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn from(value: Mask<T, LANES>) -> Self {
+        value.0
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitAnd for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitand(self, rhs: Self) -> Self {
+        unsafe { Self(intrinsics::simd_and(self.0, rhs.0)) }
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitOr for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitor(self, rhs: Self) -> Self {
+        unsafe { Self(intrinsics::simd_or(self.0, rhs.0)) }
+    }
+}
+
+impl<T, const LANES: usize> core::ops::BitXor for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn bitxor(self, rhs: Self) -> Self {
+        unsafe { Self(intrinsics::simd_xor(self.0, rhs.0)) }
+    }
+}
+
+impl<T, const LANES: usize> core::ops::Not for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    type Output = Self;
+    #[inline]
+    fn not(self) -> Self::Output {
+        Self::splat(true) ^ self
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/src/math.rs b/library/portable-simd/crates/core_simd/src/math.rs
new file mode 100644 (file)
index 0000000..2bae414
--- /dev/null
@@ -0,0 +1,159 @@
+use crate::simd::intrinsics::{simd_saturating_add, simd_saturating_sub};
+use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+
+macro_rules! impl_uint_arith {
+    ($($ty:ty),+) => {
+        $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
+
+            /// Lanewise saturating add.
+            ///
+            /// # Examples
+            /// ```
+            /// # #![feature(portable_simd)]
+            /// # #[cfg(feature = "std")] use core_simd::Simd;
+            /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+            #[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
+            /// let x = Simd::from_array([2, 1, 0, MAX]);
+            /// let max = Simd::splat(MAX);
+            /// let unsat = x + max;
+            /// let sat = x.saturating_add(max);
+            /// assert_eq!(x - 1, unsat);
+            /// assert_eq!(sat, max);
+            /// ```
+            #[inline]
+            pub fn saturating_add(self, second: Self) -> Self {
+                unsafe { simd_saturating_add(self, second) }
+            }
+
+            /// Lanewise saturating subtract.
+            ///
+            /// # Examples
+            /// ```
+            /// # #![feature(portable_simd)]
+            /// # #[cfg(feature = "std")] use core_simd::Simd;
+            /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+            #[doc = concat!("# use core::", stringify!($ty), "::MAX;")]
+            /// let x = Simd::from_array([2, 1, 0, MAX]);
+            /// let max = Simd::splat(MAX);
+            /// let unsat = x - max;
+            /// let sat = x.saturating_sub(max);
+            /// assert_eq!(unsat, x + 1);
+            /// assert_eq!(sat, Simd::splat(0));
+            #[inline]
+            pub fn saturating_sub(self, second: Self) -> Self {
+                unsafe { simd_saturating_sub(self, second) }
+            }
+        })+
+    }
+}
+
+macro_rules! impl_int_arith {
+    ($($ty:ty),+) => {
+        $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
+
+            /// Lanewise saturating add.
+            ///
+            /// # Examples
+            /// ```
+            /// # #![feature(portable_simd)]
+            /// # #[cfg(feature = "std")] use core_simd::Simd;
+            /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+            #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
+            /// let x = Simd::from_array([MIN, 0, 1, MAX]);
+            /// let max = Simd::splat(MAX);
+            /// let unsat = x + max;
+            /// let sat = x.saturating_add(max);
+            /// assert_eq!(unsat, Simd::from_array([-1, MAX, MIN, -2]));
+            /// assert_eq!(sat, Simd::from_array([-1, MAX, MAX, MAX]));
+            /// ```
+            #[inline]
+            pub fn saturating_add(self, second: Self) -> Self {
+                unsafe { simd_saturating_add(self, second) }
+            }
+
+            /// Lanewise saturating subtract.
+            ///
+            /// # Examples
+            /// ```
+            /// # #![feature(portable_simd)]
+            /// # #[cfg(feature = "std")] use core_simd::Simd;
+            /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+            #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
+            /// let x = Simd::from_array([MIN, -2, -1, MAX]);
+            /// let max = Simd::splat(MAX);
+            /// let unsat = x - max;
+            /// let sat = x.saturating_sub(max);
+            /// assert_eq!(unsat, Simd::from_array([1, MAX, MIN, 0]));
+            /// assert_eq!(sat, Simd::from_array([MIN, MIN, MIN, 0]));
+            #[inline]
+            pub fn saturating_sub(self, second: Self) -> Self {
+                unsafe { simd_saturating_sub(self, second) }
+            }
+
+            /// Lanewise absolute value, implemented in Rust.
+            /// Every lane becomes its absolute value.
+            ///
+            /// # Examples
+            /// ```
+            /// # #![feature(portable_simd)]
+            /// # #[cfg(feature = "std")] use core_simd::Simd;
+            /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+            #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
+            /// let xs = Simd::from_array([MIN, MIN +1, -5, 0]);
+            /// assert_eq!(xs.abs(), Simd::from_array([MIN, MAX, 5, 0]));
+            /// ```
+            #[inline]
+            pub fn abs(self) -> Self {
+                const SHR: $ty = <$ty>::BITS as $ty - 1;
+                let m = self >> SHR;
+                (self^m) - m
+            }
+
+            /// Lanewise saturating absolute value, implemented in Rust.
+            /// As abs(), except the MIN value becomes MAX instead of itself.
+            ///
+            /// # Examples
+            /// ```
+            /// # #![feature(portable_simd)]
+            /// # #[cfg(feature = "std")] use core_simd::Simd;
+            /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+            #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
+            /// let xs = Simd::from_array([MIN, -2, 0, 3]);
+            /// let unsat = xs.abs();
+            /// let sat = xs.saturating_abs();
+            /// assert_eq!(unsat, Simd::from_array([MIN, 2, 0, 3]));
+            /// assert_eq!(sat, Simd::from_array([MAX, 2, 0, 3]));
+            /// ```
+            #[inline]
+            pub fn saturating_abs(self) -> Self {
+                // arith shift for -1 or 0 mask based on sign bit, giving 2s complement
+                const SHR: $ty = <$ty>::BITS as $ty - 1;
+                let m = self >> SHR;
+                (self^m).saturating_sub(m)
+            }
+
+            /// Lanewise saturating negation, implemented in Rust.
+            /// As neg(), except the MIN value becomes MAX instead of itself.
+            ///
+            /// # Examples
+            /// ```
+            /// # #![feature(portable_simd)]
+            /// # #[cfg(feature = "std")] use core_simd::Simd;
+            /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+            #[doc = concat!("# use core::", stringify!($ty), "::{MIN, MAX};")]
+            /// let x = Simd::from_array([MIN, -2, 3, MAX]);
+            /// let unsat = -x;
+            /// let sat = x.saturating_neg();
+            /// assert_eq!(unsat, Simd::from_array([MIN, 2, -3, MIN + 1]));
+            /// assert_eq!(sat, Simd::from_array([MAX, 2, -3, MIN + 1]));
+            /// ```
+            #[inline]
+            pub fn saturating_neg(self) -> Self {
+                Self::splat(0).saturating_sub(self)
+            }
+        })+
+    }
+}
+
+impl_uint_arith! { u8, u16, u32, u64, usize }
+impl_int_arith! { i8, i16, i32, i64, isize }
diff --git a/library/portable-simd/crates/core_simd/src/mod.rs b/library/portable-simd/crates/core_simd/src/mod.rs
new file mode 100644 (file)
index 0000000..ec874a2
--- /dev/null
@@ -0,0 +1,33 @@
+#[macro_use]
+mod reduction;
+
+#[macro_use]
+mod swizzle;
+
+pub(crate) mod intrinsics;
+
+#[cfg(feature = "generic_const_exprs")]
+mod to_bytes;
+
+mod comparisons;
+mod fmt;
+mod iter;
+mod lane_count;
+mod masks;
+mod math;
+mod ops;
+mod round;
+mod select;
+mod vector;
+mod vendor;
+
+#[doc = include_str!("core_simd_docs.md")]
+pub mod simd {
+    pub(crate) use crate::core_simd::intrinsics;
+
+    pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount};
+    pub use crate::core_simd::masks::*;
+    pub use crate::core_simd::select::Select;
+    pub use crate::core_simd::swizzle::*;
+    pub use crate::core_simd::vector::*;
+}
diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs
new file mode 100644 (file)
index 0000000..5d7af47
--- /dev/null
@@ -0,0 +1,644 @@
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
+
+impl<I, T, const LANES: usize> core::ops::Index<I> for Simd<T, LANES>
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount,
+    I: core::slice::SliceIndex<[T]>,
+{
+    type Output = I::Output;
+    fn index(&self, index: I) -> &Self::Output {
+        &self.as_array()[index]
+    }
+}
+
+impl<I, T, const LANES: usize> core::ops::IndexMut<I> for Simd<T, LANES>
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount,
+    I: core::slice::SliceIndex<[T]>,
+{
+    fn index_mut(&mut self, index: I) -> &mut Self::Output {
+        &mut self.as_mut_array()[index]
+    }
+}
+
+/// Checks if the right-hand side argument of a left- or right-shift would cause overflow.
+fn invalid_shift_rhs<T>(rhs: T) -> bool
+where
+    T: Default + PartialOrd + core::convert::TryFrom<usize>,
+    <T as core::convert::TryFrom<usize>>::Error: core::fmt::Debug,
+{
+    let bits_in_type = T::try_from(8 * core::mem::size_of::<T>()).unwrap();
+    rhs < T::default() || rhs >= bits_in_type
+}
+
+/// Automatically implements operators over references in addition to the provided operator.
+macro_rules! impl_ref_ops {
+    // binary op
+    {
+        impl<const $lanes:ident: usize> core::ops::$trait:ident<$rhs:ty> for $type:ty
+        where
+            LaneCount<$lanes2:ident>: SupportedLaneCount,
+        {
+            type Output = $output:ty;
+
+            $(#[$attrs:meta])*
+            fn $fn:ident($self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) -> Self::Output $body:tt
+        }
+    } => {
+        impl<const $lanes: usize> core::ops::$trait<$rhs> for $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            type Output = $output;
+
+            $(#[$attrs])*
+            fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body
+        }
+
+        impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            type Output = <$type as core::ops::$trait<$rhs>>::Output;
+
+            $(#[$attrs])*
+            fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output {
+                core::ops::$trait::$fn($self_tok, *$rhs_arg)
+            }
+        }
+
+        impl<const $lanes: usize> core::ops::$trait<$rhs> for &'_ $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            type Output = <$type as core::ops::$trait<$rhs>>::Output;
+
+            $(#[$attrs])*
+            fn $fn($self_tok, $rhs_arg: $rhs) -> Self::Output {
+                core::ops::$trait::$fn(*$self_tok, $rhs_arg)
+            }
+        }
+
+        impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for &'_ $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            type Output = <$type as core::ops::$trait<$rhs>>::Output;
+
+            $(#[$attrs])*
+            fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output {
+                core::ops::$trait::$fn(*$self_tok, *$rhs_arg)
+            }
+        }
+    };
+
+    // binary assignment op
+    {
+        impl<const $lanes:ident: usize> core::ops::$trait:ident<$rhs:ty> for $type:ty
+        where
+            LaneCount<$lanes2:ident>: SupportedLaneCount,
+        {
+            $(#[$attrs:meta])*
+            fn $fn:ident(&mut $self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) $body:tt
+        }
+    } => {
+        impl<const $lanes: usize> core::ops::$trait<$rhs> for $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            $(#[$attrs])*
+            fn $fn(&mut $self_tok, $rhs_arg: $rhs_arg_ty) $body
+        }
+
+        impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            $(#[$attrs])*
+            fn $fn(&mut $self_tok, $rhs_arg: &$rhs_arg_ty) {
+                core::ops::$trait::$fn($self_tok, *$rhs_arg)
+            }
+        }
+    };
+
+    // unary op
+    {
+        impl<const $lanes:ident: usize> core::ops::$trait:ident for $type:ty
+        where
+            LaneCount<$lanes2:ident>: SupportedLaneCount,
+        {
+            type Output = $output:ty;
+            fn $fn:ident($self_tok:ident) -> Self::Output $body:tt
+        }
+    } => {
+        impl<const $lanes: usize> core::ops::$trait for $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            type Output = $output;
+            fn $fn($self_tok) -> Self::Output $body
+        }
+
+        impl<const $lanes: usize> core::ops::$trait for &'_ $type
+        where
+            LaneCount<$lanes2>: SupportedLaneCount,
+        {
+            type Output = <$type as core::ops::$trait>::Output;
+            fn $fn($self_tok) -> Self::Output {
+                core::ops::$trait::$fn(*$self_tok)
+            }
+        }
+    }
+}
+
+/// Automatically implements operators over vectors and scalars for a particular vector.
+macro_rules! impl_op {
+    { impl Add for $scalar:ty } => {
+        impl_op! { @binary $scalar, Add::add, AddAssign::add_assign, simd_add }
+    };
+    { impl Sub for $scalar:ty } => {
+        impl_op! { @binary $scalar, Sub::sub, SubAssign::sub_assign, simd_sub }
+    };
+    { impl Mul for $scalar:ty } => {
+        impl_op! { @binary $scalar, Mul::mul, MulAssign::mul_assign, simd_mul }
+    };
+    { impl Div for $scalar:ty } => {
+        impl_op! { @binary $scalar, Div::div, DivAssign::div_assign, simd_div }
+    };
+    { impl Rem for $scalar:ty } => {
+        impl_op! { @binary $scalar, Rem::rem, RemAssign::rem_assign, simd_rem }
+    };
+    { impl Shl for $scalar:ty } => {
+        impl_op! { @binary $scalar, Shl::shl, ShlAssign::shl_assign, simd_shl }
+    };
+    { impl Shr for $scalar:ty } => {
+        impl_op! { @binary $scalar, Shr::shr, ShrAssign::shr_assign, simd_shr }
+    };
+    { impl BitAnd for $scalar:ty } => {
+        impl_op! { @binary $scalar, BitAnd::bitand, BitAndAssign::bitand_assign, simd_and }
+    };
+    { impl BitOr for $scalar:ty } => {
+        impl_op! { @binary $scalar, BitOr::bitor, BitOrAssign::bitor_assign, simd_or }
+    };
+    { impl BitXor for $scalar:ty } => {
+        impl_op! { @binary $scalar, BitXor::bitxor, BitXorAssign::bitxor_assign, simd_xor }
+    };
+
+    { impl Not for $scalar:ty } => {
+        impl_ref_ops! {
+            impl<const LANES: usize> core::ops::Not for Simd<$scalar, LANES>
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                type Output = Self;
+                fn not(self) -> Self::Output {
+                    self ^ Self::splat(!<$scalar>::default())
+                }
+            }
+        }
+    };
+
+    { impl Neg for $scalar:ty } => {
+        impl_ref_ops! {
+            impl<const LANES: usize> core::ops::Neg for Simd<$scalar, LANES>
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                type Output = Self;
+                fn neg(self) -> Self::Output {
+                    unsafe { intrinsics::simd_neg(self) }
+                }
+            }
+        }
+    };
+
+    // generic binary op with assignment when output is `Self`
+    { @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $assign_trait:ident :: $assign_trait_fn:ident, $intrinsic:ident } => {
+        impl_ref_ops! {
+            impl<const LANES: usize> core::ops::$trait<Self> for Simd<$scalar, LANES>
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                type Output = Self;
+
+                #[inline]
+                fn $trait_fn(self, rhs: Self) -> Self::Output {
+                    unsafe {
+                        intrinsics::$intrinsic(self, rhs)
+                    }
+                }
+            }
+        }
+
+        impl_ref_ops! {
+            impl<const LANES: usize> core::ops::$trait<$scalar> for Simd<$scalar, LANES>
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                type Output = Self;
+
+                #[inline]
+                fn $trait_fn(self, rhs: $scalar) -> Self::Output {
+                    core::ops::$trait::$trait_fn(self, Self::splat(rhs))
+                }
+            }
+        }
+
+        impl_ref_ops! {
+            impl<const LANES: usize> core::ops::$trait<Simd<$scalar, LANES>> for $scalar
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                type Output = Simd<$scalar, LANES>;
+
+                #[inline]
+                fn $trait_fn(self, rhs: Simd<$scalar, LANES>) -> Self::Output {
+                    core::ops::$trait::$trait_fn(Simd::splat(self), rhs)
+                }
+            }
+        }
+
+        impl_ref_ops! {
+            impl<const LANES: usize> core::ops::$assign_trait<Self> for Simd<$scalar, LANES>
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                #[inline]
+                fn $assign_trait_fn(&mut self, rhs: Self) {
+                    unsafe {
+                        *self = intrinsics::$intrinsic(*self, rhs);
+                    }
+                }
+            }
+        }
+
+        impl_ref_ops! {
+            impl<const LANES: usize> core::ops::$assign_trait<$scalar> for Simd<$scalar, LANES>
+            where
+                LaneCount<LANES>: SupportedLaneCount,
+            {
+                #[inline]
+                fn $assign_trait_fn(&mut self, rhs: $scalar) {
+                    core::ops::$assign_trait::$assign_trait_fn(self, Self::splat(rhs));
+                }
+            }
+        }
+    };
+}
+
+/// Implements floating-point operators for the provided types.
+macro_rules! impl_float_ops {
+    { $($scalar:ty),* } => {
+        $(
+            impl_op! { impl Add for $scalar }
+            impl_op! { impl Sub for $scalar }
+            impl_op! { impl Mul for $scalar }
+            impl_op! { impl Div for $scalar }
+            impl_op! { impl Rem for $scalar }
+            impl_op! { impl Neg for $scalar }
+        )*
+    };
+}
+
+/// Implements unsigned integer operators for the provided types.
+macro_rules! impl_unsigned_int_ops {
+    { $($scalar:ty),* } => {
+        $(
+            impl_op! { impl Add for $scalar }
+            impl_op! { impl Sub for $scalar }
+            impl_op! { impl Mul for $scalar }
+            impl_op! { impl BitAnd for $scalar }
+            impl_op! { impl BitOr  for $scalar }
+            impl_op! { impl BitXor for $scalar }
+            impl_op! { impl Not for $scalar }
+
+            // Integers panic on divide by 0
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Div<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn div(self, rhs: Self) -> Self::Output {
+                        if rhs.as_array()
+                            .iter()
+                            .any(|x| *x == 0)
+                        {
+                            panic!("attempt to divide by zero");
+                        }
+
+                        // Guards for div(MIN, -1),
+                        // this check only applies to signed ints
+                        if <$scalar>::MIN != 0 && self.as_array().iter()
+                                .zip(rhs.as_array().iter())
+                                .any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
+                            panic!("attempt to divide with overflow");
+                        }
+                        unsafe { intrinsics::simd_div(self, rhs) }
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Div<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn div(self, rhs: $scalar) -> Self::Output {
+                        if rhs == 0 {
+                            panic!("attempt to divide by zero");
+                        }
+                        if <$scalar>::MIN != 0 &&
+                            self.as_array().iter().any(|x| *x == <$scalar>::MIN) &&
+                            rhs == -1 as _ {
+                                panic!("attempt to divide with overflow");
+                        }
+                        let rhs = Self::splat(rhs);
+                        unsafe { intrinsics::simd_div(self, rhs) }
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Div<Simd<$scalar, LANES>> for $scalar
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Simd<$scalar, LANES>;
+
+                    #[inline]
+                    fn div(self, rhs: Simd<$scalar, LANES>) -> Self::Output {
+                        Simd::splat(self) / rhs
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::DivAssign<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn div_assign(&mut self, rhs: Self) {
+                        *self = *self / rhs;
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::DivAssign<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn div_assign(&mut self, rhs: $scalar) {
+                        *self = *self / rhs;
+                    }
+                }
+            }
+
+            // remainder panics on zero divisor
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Rem<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn rem(self, rhs: Self) -> Self::Output {
+                        if rhs.as_array()
+                            .iter()
+                            .any(|x| *x == 0)
+                        {
+                            panic!("attempt to calculate the remainder with a divisor of zero");
+                        }
+
+                        // Guards for rem(MIN, -1)
+                        // this branch applies the check only to signed ints
+                        if <$scalar>::MIN != 0 && self.as_array().iter()
+                                .zip(rhs.as_array().iter())
+                                .any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
+                            panic!("attempt to calculate the remainder with overflow");
+                        }
+                        unsafe { intrinsics::simd_rem(self, rhs) }
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Rem<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn rem(self, rhs: $scalar) -> Self::Output {
+                        if rhs == 0 {
+                            panic!("attempt to calculate the remainder with a divisor of zero");
+                        }
+                        if <$scalar>::MIN != 0 &&
+                            self.as_array().iter().any(|x| *x == <$scalar>::MIN) &&
+                            rhs == -1 as _ {
+                                panic!("attempt to calculate the remainder with overflow");
+                        }
+                        let rhs = Self::splat(rhs);
+                        unsafe { intrinsics::simd_rem(self, rhs) }
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Rem<Simd<$scalar, LANES>> for $scalar
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Simd<$scalar, LANES>;
+
+                    #[inline]
+                    fn rem(self, rhs: Simd<$scalar, LANES>) -> Self::Output {
+                        Simd::splat(self) % rhs
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::RemAssign<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn rem_assign(&mut self, rhs: Self) {
+                        *self = *self % rhs;
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::RemAssign<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn rem_assign(&mut self, rhs: $scalar) {
+                        *self = *self % rhs;
+                    }
+                }
+            }
+
+            // shifts panic on overflow
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Shl<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn shl(self, rhs: Self) -> Self::Output {
+                        // TODO there is probably a better way of doing this
+                        if rhs.as_array()
+                            .iter()
+                            .copied()
+                            .any(invalid_shift_rhs)
+                        {
+                            panic!("attempt to shift left with overflow");
+                        }
+                        unsafe { intrinsics::simd_shl(self, rhs) }
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Shl<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn shl(self, rhs: $scalar) -> Self::Output {
+                        if invalid_shift_rhs(rhs) {
+                            panic!("attempt to shift left with overflow");
+                        }
+                        let rhs = Self::splat(rhs);
+                        unsafe { intrinsics::simd_shl(self, rhs) }
+                    }
+                }
+            }
+
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::ShlAssign<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn shl_assign(&mut self, rhs: Self) {
+                        *self = *self << rhs;
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::ShlAssign<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn shl_assign(&mut self, rhs: $scalar) {
+                        *self = *self << rhs;
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Shr<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn shr(self, rhs: Self) -> Self::Output {
+                        // TODO there is probably a better way of doing this
+                        if rhs.as_array()
+                            .iter()
+                            .copied()
+                            .any(invalid_shift_rhs)
+                        {
+                            panic!("attempt to shift with overflow");
+                        }
+                        unsafe { intrinsics::simd_shr(self, rhs) }
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::Shr<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    type Output = Self;
+
+                    #[inline]
+                    fn shr(self, rhs: $scalar) -> Self::Output {
+                        if invalid_shift_rhs(rhs) {
+                            panic!("attempt to shift with overflow");
+                        }
+                        let rhs = Self::splat(rhs);
+                        unsafe { intrinsics::simd_shr(self, rhs) }
+                    }
+                }
+            }
+
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::ShrAssign<Self> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn shr_assign(&mut self, rhs: Self) {
+                        *self = *self >> rhs;
+                    }
+                }
+            }
+
+            impl_ref_ops! {
+                impl<const LANES: usize> core::ops::ShrAssign<$scalar> for Simd<$scalar, LANES>
+                where
+                    LaneCount<LANES>: SupportedLaneCount,
+                {
+                    #[inline]
+                    fn shr_assign(&mut self, rhs: $scalar) {
+                        *self = *self >> rhs;
+                    }
+                }
+            }
+        )*
+    };
+}
+
+/// Implements unsigned integer operators for the provided types.
+macro_rules! impl_signed_int_ops {
+    { $($scalar:ty),* } => {
+        impl_unsigned_int_ops! { $($scalar),* }
+        $( // scalar
+            impl_op! { impl Neg for $scalar }
+        )*
+    };
+}
+
+impl_unsigned_int_ops! { u8, u16, u32, u64, usize }
+impl_signed_int_ops! { i8, i16, i32, i64, isize }
+impl_float_ops! { f32, f64 }
diff --git a/library/portable-simd/crates/core_simd/src/reduction.rs b/library/portable-simd/crates/core_simd/src/reduction.rs
new file mode 100644 (file)
index 0000000..db0640a
--- /dev/null
@@ -0,0 +1,123 @@
+use crate::simd::intrinsics::{
+    simd_reduce_add_ordered, simd_reduce_and, simd_reduce_max, simd_reduce_min,
+    simd_reduce_mul_ordered, simd_reduce_or, simd_reduce_xor,
+};
+use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+
+macro_rules! impl_integer_reductions {
+    { $scalar:ty } => {
+        impl<const LANES: usize> Simd<$scalar, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            /// Horizontal wrapping add.  Returns the sum of the lanes of the vector, with wrapping addition.
+            #[inline]
+            pub fn horizontal_sum(self) -> $scalar {
+                unsafe { simd_reduce_add_ordered(self, 0) }
+            }
+
+            /// Horizontal wrapping multiply.  Returns the product of the lanes of the vector, with wrapping multiplication.
+            #[inline]
+            pub fn horizontal_product(self) -> $scalar {
+                unsafe { simd_reduce_mul_ordered(self, 1) }
+            }
+
+            /// Horizontal bitwise "and".  Returns the cumulative bitwise "and" across the lanes of
+            /// the vector.
+            #[inline]
+            pub fn horizontal_and(self) -> $scalar {
+                unsafe { simd_reduce_and(self) }
+            }
+
+            /// Horizontal bitwise "or".  Returns the cumulative bitwise "or" across the lanes of
+            /// the vector.
+            #[inline]
+            pub fn horizontal_or(self) -> $scalar {
+                unsafe { simd_reduce_or(self) }
+            }
+
+            /// Horizontal bitwise "xor".  Returns the cumulative bitwise "xor" across the lanes of
+            /// the vector.
+            #[inline]
+            pub fn horizontal_xor(self) -> $scalar {
+                unsafe { simd_reduce_xor(self) }
+            }
+
+            /// Horizontal maximum.  Returns the maximum lane in the vector.
+            #[inline]
+            pub fn horizontal_max(self) -> $scalar {
+                unsafe { simd_reduce_max(self) }
+            }
+
+            /// Horizontal minimum.  Returns the minimum lane in the vector.
+            #[inline]
+            pub fn horizontal_min(self) -> $scalar {
+                unsafe { simd_reduce_min(self) }
+            }
+        }
+    }
+}
+
+impl_integer_reductions! { i8 }
+impl_integer_reductions! { i16 }
+impl_integer_reductions! { i32 }
+impl_integer_reductions! { i64 }
+impl_integer_reductions! { isize }
+impl_integer_reductions! { u8 }
+impl_integer_reductions! { u16 }
+impl_integer_reductions! { u32 }
+impl_integer_reductions! { u64 }
+impl_integer_reductions! { usize }
+
+macro_rules! impl_float_reductions {
+    { $scalar:ty } => {
+        impl<const LANES: usize> Simd<$scalar, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+
+            /// Horizontal add.  Returns the sum of the lanes of the vector.
+            #[inline]
+            pub fn horizontal_sum(self) -> $scalar {
+                // LLVM sum is inaccurate on i586
+                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
+                    self.as_array().iter().sum()
+                } else {
+                    unsafe { simd_reduce_add_ordered(self, 0.) }
+                }
+            }
+
+            /// Horizontal multiply.  Returns the product of the lanes of the vector.
+            #[inline]
+            pub fn horizontal_product(self) -> $scalar {
+                // LLVM product is inaccurate on i586
+                if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
+                    self.as_array().iter().product()
+                } else {
+                    unsafe { simd_reduce_mul_ordered(self, 1.) }
+                }
+            }
+
+            /// Horizontal maximum.  Returns the maximum lane in the vector.
+            ///
+            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
+            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
+            #[inline]
+            pub fn horizontal_max(self) -> $scalar {
+                unsafe { simd_reduce_max(self) }
+            }
+
+            /// Horizontal minimum.  Returns the minimum lane in the vector.
+            ///
+            /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
+            /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
+            #[inline]
+            pub fn horizontal_min(self) -> $scalar {
+                unsafe { simd_reduce_min(self) }
+            }
+        }
+    }
+}
+
+impl_float_reductions! { f32 }
+impl_float_reductions! { f64 }
diff --git a/library/portable-simd/crates/core_simd/src/round.rs b/library/portable-simd/crates/core_simd/src/round.rs
new file mode 100644 (file)
index 0000000..09789e1
--- /dev/null
@@ -0,0 +1,78 @@
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+
+macro_rules! implement {
+    {
+        $type:ty, $int_type:ty
+    } => {
+        #[cfg(feature = "std")]
+        impl<const LANES: usize> Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            /// Returns the smallest integer greater than or equal to each lane.
+            #[must_use = "method returns a new vector and does not mutate the original value"]
+            #[inline]
+            pub fn ceil(self) -> Self {
+                unsafe { intrinsics::simd_ceil(self) }
+            }
+
+            /// Returns the largest integer value less than or equal to each lane.
+            #[must_use = "method returns a new vector and does not mutate the original value"]
+            #[inline]
+            pub fn floor(self) -> Self {
+                unsafe { intrinsics::simd_floor(self) }
+            }
+
+            /// Rounds to the nearest integer value. Ties round toward zero.
+            #[must_use = "method returns a new vector and does not mutate the original value"]
+            #[inline]
+            pub fn round(self) -> Self {
+                unsafe { intrinsics::simd_round(self) }
+            }
+
+            /// Returns the floating point's integer value, with its fractional part removed.
+            #[must_use = "method returns a new vector and does not mutate the original value"]
+            #[inline]
+            pub fn trunc(self) -> Self {
+                unsafe { intrinsics::simd_trunc(self) }
+            }
+
+            /// Returns the floating point's fractional value, with its integer part removed.
+            #[must_use = "method returns a new vector and does not mutate the original value"]
+            #[inline]
+            pub fn fract(self) -> Self {
+                self - self.trunc()
+            }
+        }
+
+        impl<const LANES: usize> Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            /// Rounds toward zero and converts to the same-width integer type, assuming that
+            /// the value is finite and fits in that type.
+            ///
+            /// # Safety
+            /// The value must:
+            ///
+            /// * Not be NaN
+            /// * Not be infinite
+            /// * Be representable in the return type, after truncating off its fractional part
+            #[inline]
+            pub unsafe fn to_int_unchecked(self) -> Simd<$int_type, LANES> {
+                unsafe { intrinsics::simd_cast(self) }
+            }
+
+            /// Creates a floating-point vector from an integer vector.  Rounds values that are
+            /// not exactly representable.
+            #[inline]
+            pub fn round_from_int(value: Simd<$int_type, LANES>) -> Self {
+                unsafe { intrinsics::simd_cast(value) }
+            }
+        }
+    }
+}
+
+implement! { f32, i32 }
+implement! { f64, i64 }
diff --git a/library/portable-simd/crates/core_simd/src/select.rs b/library/portable-simd/crates/core_simd/src/select.rs
new file mode 100644 (file)
index 0000000..d976231
--- /dev/null
@@ -0,0 +1,86 @@
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount};
+
+mod sealed {
+    pub trait Sealed<Mask> {
+        fn select(mask: Mask, true_values: Self, false_values: Self) -> Self;
+    }
+}
+use sealed::Sealed;
+
+/// Supporting trait for vector `select` function
+pub trait Select<Mask>: Sealed<Mask> {}
+
+impl<T, const LANES: usize> Sealed<Mask<T::Mask, LANES>> for Simd<T, LANES>
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn select(mask: Mask<T::Mask, LANES>, true_values: Self, false_values: Self) -> Self {
+        unsafe { intrinsics::simd_select(mask.to_int(), true_values, false_values) }
+    }
+}
+
+impl<T, const LANES: usize> Select<Mask<T::Mask, LANES>> for Simd<T, LANES>
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Sealed<Self> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    #[inline]
+    fn select(mask: Self, true_values: Self, false_values: Self) -> Self {
+        mask & true_values | !mask & false_values
+    }
+}
+
+impl<T, const LANES: usize> Select<Self> for Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Mask<T, LANES>
+where
+    T: MaskElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    /// Choose lanes from two vectors.
+    ///
+    /// For each lane in the mask, choose the corresponding lane from `true_values` if
+    /// that lane mask is true, and `false_values` if that lane mask is false.
+    ///
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
+    /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
+    /// let a = Simd::from_array([0, 1, 2, 3]);
+    /// let b = Simd::from_array([4, 5, 6, 7]);
+    /// let mask = Mask::from_array([true, false, false, true]);
+    /// let c = mask.select(a, b);
+    /// assert_eq!(c.to_array(), [0, 5, 6, 3]);
+    /// ```
+    ///
+    /// `select` can also be used on masks:
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::Mask;
+    /// # #[cfg(not(feature = "std"))] use core::simd::Mask;
+    /// let a = Mask::<i32, 4>::from_array([true, true, false, false]);
+    /// let b = Mask::<i32, 4>::from_array([false, false, true, true]);
+    /// let mask = Mask::<i32, 4>::from_array([true, false, false, true]);
+    /// let c = mask.select(a, b);
+    /// assert_eq!(c.to_array(), [true, false, true, false]);
+    /// ```
+    #[inline]
+    pub fn select<S: Select<Self>>(self, true_values: S, false_values: S) -> S {
+        S::select(self, true_values, false_values)
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs
new file mode 100644 (file)
index 0000000..62cda68
--- /dev/null
@@ -0,0 +1,374 @@
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
+
+/// Constructs a new vector by selecting values from the lanes of the source vector or vectors to use.
+///
+/// When swizzling one vector, the indices of the result vector are indicated by a `const` array
+/// of `usize`, like [`Swizzle`].
+/// When swizzling two vectors, the indices are indicated by a `const` array of [`Which`], like
+/// [`Swizzle2`].
+///
+/// # Examples
+/// ## One source vector
+/// ```
+/// # #![feature(portable_simd)]
+/// # #[cfg(feature = "std")] use core_simd::{Simd, simd_swizzle};
+/// # #[cfg(not(feature = "std"))] use core::simd::{Simd, simd_swizzle};
+/// let v = Simd::<f32, 4>::from_array([0., 1., 2., 3.]);
+///
+/// // Keeping the same size
+/// let r = simd_swizzle!(v, [3, 0, 1, 2]);
+/// assert_eq!(r.to_array(), [3., 0., 1., 2.]);
+///
+/// // Changing the number of lanes
+/// let r = simd_swizzle!(v, [3, 1]);
+/// assert_eq!(r.to_array(), [3., 1.]);
+/// ```
+///
+/// ## Two source vectors
+/// ```
+/// # #![feature(portable_simd)]
+/// # #[cfg(feature = "std")] use core_simd::{Simd, simd_swizzle, Which};
+/// # #[cfg(not(feature = "std"))] use core::simd::{Simd, simd_swizzle, Which};
+/// use Which::*;
+/// let a = Simd::<f32, 4>::from_array([0., 1., 2., 3.]);
+/// let b = Simd::<f32, 4>::from_array([4., 5., 6., 7.]);
+///
+/// // Keeping the same size
+/// let r = simd_swizzle!(a, b, [First(0), First(1), Second(2), Second(3)]);
+/// assert_eq!(r.to_array(), [0., 1., 6., 7.]);
+///
+/// // Changing the number of lanes
+/// let r = simd_swizzle!(a, b, [First(0), Second(0)]);
+/// assert_eq!(r.to_array(), [0., 4.]);
+/// ```
+#[allow(unused_macros)]
+pub macro simd_swizzle {
+    (
+        $vector:expr, $index:expr $(,)?
+    ) => {
+        {
+            use $crate::simd::Swizzle;
+            struct Impl;
+            impl<const LANES: usize> Swizzle<LANES, {$index.len()}> for Impl {
+                const INDEX: [usize; {$index.len()}] = $index;
+            }
+            Impl::swizzle($vector)
+        }
+    },
+    (
+        $first:expr, $second:expr, $index:expr $(,)?
+    ) => {
+        {
+            use $crate::simd::{Which, Swizzle2};
+            struct Impl;
+            impl<const LANES: usize> Swizzle2<LANES, {$index.len()}> for Impl {
+                const INDEX: [Which; {$index.len()}] = $index;
+            }
+            Impl::swizzle2($first, $second)
+        }
+    }
+}
+
+/// An index into one of two vectors.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum Which {
+    /// Indexes the first vector.
+    First(usize),
+    /// Indexes the second vector.
+    Second(usize),
+}
+
+/// Create a vector from the elements of another vector.
+pub trait Swizzle<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
+    /// Map from the lanes of the input vector to the output vector.
+    const INDEX: [usize; OUTPUT_LANES];
+
+    /// Create a new vector from the lanes of `vector`.
+    ///
+    /// Lane `i` of the output is `vector[Self::INDEX[i]]`.
+    fn swizzle<T>(vector: Simd<T, INPUT_LANES>) -> Simd<T, OUTPUT_LANES>
+    where
+        T: SimdElement,
+        LaneCount<INPUT_LANES>: SupportedLaneCount,
+        LaneCount<OUTPUT_LANES>: SupportedLaneCount,
+    {
+        unsafe { intrinsics::simd_shuffle(vector, vector, Self::INDEX_IMPL) }
+    }
+}
+
+/// Create a vector from the elements of two other vectors.
+pub trait Swizzle2<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
+    /// Map from the lanes of the input vectors to the output vector
+    const INDEX: [Which; OUTPUT_LANES];
+
+    /// Create a new vector from the lanes of `first` and `second`.
+    ///
+    /// Lane `i` is `first[j]` when `Self::INDEX[i]` is `First(j)`, or `second[j]` when it is
+    /// `Second(j)`.
+    fn swizzle2<T>(
+        first: Simd<T, INPUT_LANES>,
+        second: Simd<T, INPUT_LANES>,
+    ) -> Simd<T, OUTPUT_LANES>
+    where
+        T: SimdElement,
+        LaneCount<INPUT_LANES>: SupportedLaneCount,
+        LaneCount<OUTPUT_LANES>: SupportedLaneCount,
+    {
+        unsafe { intrinsics::simd_shuffle(first, second, Self::INDEX_IMPL) }
+    }
+}
+
+/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here.
+/// This trait hides `INDEX_IMPL` from the public API.
+trait SwizzleImpl<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
+    const INDEX_IMPL: [u32; OUTPUT_LANES];
+}
+
+impl<T, const INPUT_LANES: usize, const OUTPUT_LANES: usize> SwizzleImpl<INPUT_LANES, OUTPUT_LANES>
+    for T
+where
+    T: Swizzle<INPUT_LANES, OUTPUT_LANES> + ?Sized,
+{
+    const INDEX_IMPL: [u32; OUTPUT_LANES] = {
+        let mut output = [0; OUTPUT_LANES];
+        let mut i = 0;
+        while i < OUTPUT_LANES {
+            let index = Self::INDEX[i];
+            assert!(index as u32 as usize == index);
+            assert!(index < INPUT_LANES, "source lane exceeds input lane count",);
+            output[i] = index as u32;
+            i += 1;
+        }
+        output
+    };
+}
+
+/// The `simd_shuffle` intrinsic expects `u32`, so do error checking and conversion here.
+/// This trait hides `INDEX_IMPL` from the public API.
+trait Swizzle2Impl<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
+    const INDEX_IMPL: [u32; OUTPUT_LANES];
+}
+
+impl<T, const INPUT_LANES: usize, const OUTPUT_LANES: usize> Swizzle2Impl<INPUT_LANES, OUTPUT_LANES>
+    for T
+where
+    T: Swizzle2<INPUT_LANES, OUTPUT_LANES> + ?Sized,
+{
+    const INDEX_IMPL: [u32; OUTPUT_LANES] = {
+        let mut output = [0; OUTPUT_LANES];
+        let mut i = 0;
+        while i < OUTPUT_LANES {
+            let (offset, index) = match Self::INDEX[i] {
+                Which::First(index) => (false, index),
+                Which::Second(index) => (true, index),
+            };
+            assert!(index < INPUT_LANES, "source lane exceeds input lane count",);
+
+            // lanes are indexed by the first vector, then second vector
+            let index = if offset { index + INPUT_LANES } else { index };
+            assert!(index as u32 as usize == index);
+            output[i] = index as u32;
+            i += 1;
+        }
+        output
+    };
+}
+
+impl<T, const LANES: usize> Simd<T, LANES>
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    /// Reverse the order of the lanes in the vector.
+    #[inline]
+    pub fn reverse(self) -> Self {
+        const fn reverse_index<const LANES: usize>() -> [usize; LANES] {
+            let mut index = [0; LANES];
+            let mut i = 0;
+            while i < LANES {
+                index[i] = LANES - i - 1;
+                i += 1;
+            }
+            index
+        }
+
+        struct Reverse;
+
+        impl<const LANES: usize> Swizzle<LANES, LANES> for Reverse {
+            const INDEX: [usize; LANES] = reverse_index::<LANES>();
+        }
+
+        Reverse::swizzle(self)
+    }
+
+    /// Rotates the vector such that the first `OFFSET` elements of the slice move to the end
+    /// while the last `LANES - OFFSET` elements move to the front. After calling `rotate_lanes_left`,
+    /// the element previously in lane `OFFSET` will become the first element in the slice.
+    #[inline]
+    pub fn rotate_lanes_left<const OFFSET: usize>(self) -> Self {
+        const fn rotate_index<const OFFSET: usize, const LANES: usize>() -> [usize; LANES] {
+            let offset = OFFSET % LANES;
+            let mut index = [0; LANES];
+            let mut i = 0;
+            while i < LANES {
+                index[i] = (i + offset) % LANES;
+                i += 1;
+            }
+            index
+        }
+
+        struct Rotate<const OFFSET: usize>;
+
+        impl<const OFFSET: usize, const LANES: usize> Swizzle<LANES, LANES> for Rotate<OFFSET> {
+            const INDEX: [usize; LANES] = rotate_index::<OFFSET, LANES>();
+        }
+
+        Rotate::<OFFSET>::swizzle(self)
+    }
+
+    /// Rotates the vector such that the first `LANES - OFFSET` elements of the vector move to
+    /// the end while the last `OFFSET` elements move to the front. After calling `rotate_lanes_right`,
+    /// the element previously at index `LANES - OFFSET` will become the first element in the slice.
+    #[inline]
+    pub fn rotate_lanes_right<const OFFSET: usize>(self) -> Self {
+        const fn rotate_index<const OFFSET: usize, const LANES: usize>() -> [usize; LANES] {
+            let offset = LANES - OFFSET % LANES;
+            let mut index = [0; LANES];
+            let mut i = 0;
+            while i < LANES {
+                index[i] = (i + offset) % LANES;
+                i += 1;
+            }
+            index
+        }
+
+        struct Rotate<const OFFSET: usize>;
+
+        impl<const OFFSET: usize, const LANES: usize> Swizzle<LANES, LANES> for Rotate<OFFSET> {
+            const INDEX: [usize; LANES] = rotate_index::<OFFSET, LANES>();
+        }
+
+        Rotate::<OFFSET>::swizzle(self)
+    }
+
+    /// Interleave two vectors.
+    ///
+    /// Produces two vectors with lanes taken alternately from `self` and `other`.
+    ///
+    /// The first result contains the first `LANES / 2` lanes from `self` and `other`,
+    /// alternating, starting with the first lane of `self`.
+    ///
+    /// The second result contains the last `LANES / 2` lanes from `self` and `other`,
+    /// alternating, starting with the lane `LANES / 2` from the start of `self`.
+    ///
+    /// ```
+    /// #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::Simd;
+    /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+    /// let a = Simd::from_array([0, 1, 2, 3]);
+    /// let b = Simd::from_array([4, 5, 6, 7]);
+    /// let (x, y) = a.interleave(b);
+    /// assert_eq!(x.to_array(), [0, 4, 1, 5]);
+    /// assert_eq!(y.to_array(), [2, 6, 3, 7]);
+    /// ```
+    #[inline]
+    pub fn interleave(self, other: Self) -> (Self, Self) {
+        const fn lo<const LANES: usize>() -> [Which; LANES] {
+            let mut idx = [Which::First(0); LANES];
+            let mut i = 0;
+            while i < LANES {
+                let offset = i / 2;
+                idx[i] = if i % 2 == 0 {
+                    Which::First(offset)
+                } else {
+                    Which::Second(offset)
+                };
+                i += 1;
+            }
+            idx
+        }
+        const fn hi<const LANES: usize>() -> [Which; LANES] {
+            let mut idx = [Which::First(0); LANES];
+            let mut i = 0;
+            while i < LANES {
+                let offset = (LANES + i) / 2;
+                idx[i] = if i % 2 == 0 {
+                    Which::First(offset)
+                } else {
+                    Which::Second(offset)
+                };
+                i += 1;
+            }
+            idx
+        }
+
+        struct Lo;
+        struct Hi;
+
+        impl<const LANES: usize> Swizzle2<LANES, LANES> for Lo {
+            const INDEX: [Which; LANES] = lo::<LANES>();
+        }
+
+        impl<const LANES: usize> Swizzle2<LANES, LANES> for Hi {
+            const INDEX: [Which; LANES] = hi::<LANES>();
+        }
+
+        (Lo::swizzle2(self, other), Hi::swizzle2(self, other))
+    }
+
+    /// Deinterleave two vectors.
+    ///
+    /// The first result takes every other lane of `self` and then `other`, starting with
+    /// the first lane.
+    ///
+    /// The second result takes every other lane of `self` and then `other`, starting with
+    /// the second lane.
+    ///
+    /// ```
+    /// #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::Simd;
+    /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+    /// let a = Simd::from_array([0, 4, 1, 5]);
+    /// let b = Simd::from_array([2, 6, 3, 7]);
+    /// let (x, y) = a.deinterleave(b);
+    /// assert_eq!(x.to_array(), [0, 1, 2, 3]);
+    /// assert_eq!(y.to_array(), [4, 5, 6, 7]);
+    /// ```
+    #[inline]
+    pub fn deinterleave(self, other: Self) -> (Self, Self) {
+        const fn even<const LANES: usize>() -> [Which; LANES] {
+            let mut idx = [Which::First(0); LANES];
+            let mut i = 0;
+            while i < LANES / 2 {
+                idx[i] = Which::First(2 * i);
+                idx[i + LANES / 2] = Which::Second(2 * i);
+                i += 1;
+            }
+            idx
+        }
+        const fn odd<const LANES: usize>() -> [Which; LANES] {
+            let mut idx = [Which::First(0); LANES];
+            let mut i = 0;
+            while i < LANES / 2 {
+                idx[i] = Which::First(2 * i + 1);
+                idx[i + LANES / 2] = Which::Second(2 * i + 1);
+                i += 1;
+            }
+            idx
+        }
+
+        struct Even;
+        struct Odd;
+
+        impl<const LANES: usize> Swizzle2<LANES, LANES> for Even {
+            const INDEX: [Which; LANES] = even::<LANES>();
+        }
+
+        impl<const LANES: usize> Swizzle2<LANES, LANES> for Odd {
+            const INDEX: [Which; LANES] = odd::<LANES>();
+        }
+
+        (Even::swizzle2(self, other), Odd::swizzle2(self, other))
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/src/to_bytes.rs b/library/portable-simd/crates/core_simd/src/to_bytes.rs
new file mode 100644 (file)
index 0000000..8d9b3e8
--- /dev/null
@@ -0,0 +1,39 @@
+macro_rules! impl_to_bytes {
+    { $ty:ty, $size:literal } => {
+        impl<const LANES: usize> crate::simd::Simd<$ty, LANES>
+        where
+            crate::simd::LaneCount<LANES>: crate::simd::SupportedLaneCount,
+            crate::simd::LaneCount<{{ $size * LANES }}>: crate::simd::SupportedLaneCount,
+        {
+            /// Return the memory representation of this integer as a byte array in native byte
+            /// order.
+            pub fn to_ne_bytes(self) -> crate::simd::Simd<u8, {{ $size * LANES }}> {
+                unsafe { core::mem::transmute_copy(&self) }
+            }
+
+            /// Create a native endian integer value from its memory representation as a byte array
+            /// in native endianness.
+            pub fn from_ne_bytes(bytes: crate::simd::Simd<u8, {{ $size * LANES }}>) -> Self {
+                unsafe { core::mem::transmute_copy(&bytes) }
+            }
+        }
+    }
+}
+
+impl_to_bytes! { u8, 1 }
+impl_to_bytes! { u16, 2 }
+impl_to_bytes! { u32, 4 }
+impl_to_bytes! { u64, 8 }
+#[cfg(target_pointer_width = "32")]
+impl_to_bytes! { usize, 4 }
+#[cfg(target_pointer_width = "64")]
+impl_to_bytes! { usize, 8 }
+
+impl_to_bytes! { i8, 1 }
+impl_to_bytes! { i16, 2 }
+impl_to_bytes! { i32, 4 }
+impl_to_bytes! { i64, 8 }
+#[cfg(target_pointer_width = "32")]
+impl_to_bytes! { isize, 4 }
+#[cfg(target_pointer_width = "64")]
+impl_to_bytes! { isize, 8 }
diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs
new file mode 100644 (file)
index 0000000..7c5ec2b
--- /dev/null
@@ -0,0 +1,528 @@
+mod float;
+mod int;
+mod uint;
+
+pub use float::*;
+pub use int::*;
+pub use uint::*;
+
+// Vectors of pointers are not for public use at the current time.
+pub(crate) mod ptr;
+
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Mask, MaskElement, SupportedLaneCount};
+
+/// A SIMD vector of `LANES` elements of type `T`.
+#[repr(simd)]
+pub struct Simd<T, const LANES: usize>([T; LANES])
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount;
+
+impl<T, const LANES: usize> Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement,
+{
+    /// Number of lanes in this vector.
+    pub const LANES: usize = LANES;
+
+    /// Get the number of lanes in this vector.
+    pub const fn lanes(&self) -> usize {
+        LANES
+    }
+
+    /// Construct a SIMD vector by setting all lanes to the given value.
+    pub const fn splat(value: T) -> Self {
+        Self([value; LANES])
+    }
+
+    /// Returns an array reference containing the entire SIMD vector.
+    pub const fn as_array(&self) -> &[T; LANES] {
+        &self.0
+    }
+
+    /// Returns a mutable array reference containing the entire SIMD vector.
+    pub fn as_mut_array(&mut self) -> &mut [T; LANES] {
+        &mut self.0
+    }
+
+    /// Converts an array to a SIMD vector.
+    pub const fn from_array(array: [T; LANES]) -> Self {
+        Self(array)
+    }
+
+    /// Converts a SIMD vector to an array.
+    pub const fn to_array(self) -> [T; LANES] {
+        self.0
+    }
+
+    /// Converts a slice to a SIMD vector containing `slice[..LANES]`
+    /// # Panics
+    /// `from_slice` will panic if the slice's `len` is less than the vector's `Simd::LANES`.
+    #[must_use]
+    pub const fn from_slice(slice: &[T]) -> Self {
+        assert!(
+            slice.len() >= LANES,
+            "slice length must be at least the number of lanes"
+        );
+        let mut array = [slice[0]; LANES];
+        let mut i = 0;
+        while i < LANES {
+            array[i] = slice[i];
+            i += 1;
+        }
+        Self(array)
+    }
+
+    /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
+    /// If an index is out-of-bounds, the lane is instead selected from the `or` vector.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::Simd;
+    /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+    /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    /// let idxs = Simd::from_array([9, 3, 0, 5]);
+    /// let alt = Simd::from_array([-5, -4, -3, -2]);
+    ///
+    /// let result = Simd::gather_or(&vec, idxs, alt); // Note the lane that is out-of-bounds.
+    /// assert_eq!(result, Simd::from_array([-5, 13, 10, 15]));
+    /// ```
+    #[must_use]
+    #[inline]
+    pub fn gather_or(slice: &[T], idxs: Simd<usize, LANES>, or: Self) -> Self {
+        Self::gather_select(slice, Mask::splat(true), idxs, or)
+    }
+
+    /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
+    /// If an index is out-of-bounds, the lane is set to the default value for the type.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::Simd;
+    /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+    /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    /// let idxs = Simd::from_array([9, 3, 0, 5]);
+    ///
+    /// let result = Simd::gather_or_default(&vec, idxs); // Note the lane that is out-of-bounds.
+    /// assert_eq!(result, Simd::from_array([0, 13, 10, 15]));
+    /// ```
+    #[must_use]
+    #[inline]
+    pub fn gather_or_default(slice: &[T], idxs: Simd<usize, LANES>) -> Self
+    where
+        T: Default,
+    {
+        Self::gather_or(slice, idxs, Self::splat(T::default()))
+    }
+
+    /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
+    /// The mask `enable`s all `true` lanes and disables all `false` lanes.
+    /// If an index is disabled or is out-of-bounds, the lane is selected from the `or` vector.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
+    /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
+    /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    /// let idxs = Simd::from_array([9, 3, 0, 5]);
+    /// let alt = Simd::from_array([-5, -4, -3, -2]);
+    /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
+    ///
+    /// let result = Simd::gather_select(&vec, enable, idxs, alt); // Note the lane that is out-of-bounds.
+    /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2]));
+    /// ```
+    #[must_use]
+    #[inline]
+    pub fn gather_select(
+        slice: &[T],
+        enable: Mask<isize, LANES>,
+        idxs: Simd<usize, LANES>,
+        or: Self,
+    ) -> Self {
+        let enable: Mask<isize, LANES> = enable & idxs.lanes_lt(Simd::splat(slice.len()));
+        // SAFETY: We have masked-off out-of-bounds lanes.
+        unsafe { Self::gather_select_unchecked(slice, enable, idxs, or) }
+    }
+
+    /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
+    /// The mask `enable`s all `true` lanes and disables all `false` lanes.
+    /// If an index is disabled, the lane is selected from the `or` vector.
+    ///
+    /// # Safety
+    ///
+    /// Calling this function with an `enable`d out-of-bounds index is *[undefined behavior]*
+    /// even if the resulting value is not used.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
+    /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
+    /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    /// let idxs = Simd::from_array([9, 3, 0, 5]);
+    /// let alt = Simd::from_array([-5, -4, -3, -2]);
+    /// let enable = Mask::from_array([true, true, true, false]); // Note the final mask lane.
+    /// // If this mask was used to gather, it would be unsound. Let's fix that.
+    /// let enable = enable & idxs.lanes_lt(Simd::splat(vec.len()));
+    ///
+    /// // We have masked the OOB lane, so it's safe to gather now.
+    /// let result = unsafe { Simd::gather_select_unchecked(&vec, enable, idxs, alt) };
+    /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2]));
+    /// ```
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    #[must_use]
+    #[inline]
+    pub unsafe fn gather_select_unchecked(
+        slice: &[T],
+        enable: Mask<isize, LANES>,
+        idxs: Simd<usize, LANES>,
+        or: Self,
+    ) -> Self {
+        let base_ptr = crate::simd::ptr::SimdConstPtr::splat(slice.as_ptr());
+        // Ferris forgive me, I have done pointer arithmetic here.
+        let ptrs = base_ptr.wrapping_add(idxs);
+        // SAFETY: The ptrs have been bounds-masked to prevent memory-unsafe reads insha'allah
+        unsafe { intrinsics::simd_gather(or, ptrs, enable.to_int()) }
+    }
+
+    /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`.
+    /// If two lanes in the scattered vector would write to the same index
+    /// only the last lane is guaranteed to actually be written.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::Simd;
+    /// # #[cfg(not(feature = "std"))] use core::simd::Simd;
+    /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    /// let idxs = Simd::from_array([9, 3, 0, 0]);
+    /// let vals = Simd::from_array([-27, 82, -41, 124]);
+    ///
+    /// vals.scatter(&mut vec, idxs); // index 0 receives two writes.
+    /// assert_eq!(vec, vec![124, 11, 12, 82, 14, 15, 16, 17, 18]);
+    /// ```
+    #[inline]
+    pub fn scatter(self, slice: &mut [T], idxs: Simd<usize, LANES>) {
+        self.scatter_select(slice, Mask::splat(true), idxs)
+    }
+
+    /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`.
+    /// The mask `enable`s all `true` lanes and disables all `false` lanes.
+    /// If an enabled index is out-of-bounds, the lane is not written.
+    /// If two enabled lanes in the scattered vector would write to the same index,
+    /// only the last lane is guaranteed to actually be written.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
+    /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
+    /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    /// let idxs = Simd::from_array([9, 3, 0, 0]);
+    /// let vals = Simd::from_array([-27, 82, -41, 124]);
+    /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
+    ///
+    /// vals.scatter_select(&mut vec, enable, idxs); // index 0's second write is masked, thus omitted.
+    /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]);
+    /// ```
+    #[inline]
+    pub fn scatter_select(
+        self,
+        slice: &mut [T],
+        enable: Mask<isize, LANES>,
+        idxs: Simd<usize, LANES>,
+    ) {
+        let enable: Mask<isize, LANES> = enable & idxs.lanes_lt(Simd::splat(slice.len()));
+        // SAFETY: We have masked-off out-of-bounds lanes.
+        unsafe { self.scatter_select_unchecked(slice, enable, idxs) }
+    }
+
+    /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`.
+    /// The mask `enable`s all `true` lanes and disables all `false` lanes.
+    /// If two enabled lanes in the scattered vector would write to the same index,
+    /// only the last lane is guaranteed to actually be written.
+    ///
+    /// # Safety
+    ///
+    /// Calling this function with an enabled out-of-bounds index is *[undefined behavior]*,
+    /// and may lead to memory corruption.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(portable_simd)]
+    /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
+    /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
+    /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+    /// let idxs = Simd::from_array([9, 3, 0, 0]);
+    /// let vals = Simd::from_array([-27, 82, -41, 124]);
+    /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
+    /// // If this mask was used to scatter, it would be unsound. Let's fix that.
+    /// let enable = enable & idxs.lanes_lt(Simd::splat(vec.len()));
+    ///
+    /// // We have masked the OOB lane, so it's safe to scatter now.
+    /// unsafe { vals.scatter_select_unchecked(&mut vec, enable, idxs); }
+    /// // index 0's second write is masked, thus was omitted.
+    /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]);
+    /// ```
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    #[inline]
+    pub unsafe fn scatter_select_unchecked(
+        self,
+        slice: &mut [T],
+        enable: Mask<isize, LANES>,
+        idxs: Simd<usize, LANES>,
+    ) {
+        // SAFETY: This block works with *mut T derived from &mut 'a [T],
+        // which means it is delicate in Rust's borrowing model, circa 2021:
+        // &mut 'a [T] asserts uniqueness, so deriving &'a [T] invalidates live *mut Ts!
+        // Even though this block is largely safe methods, it must be exactly this way
+        // to prevent invalidating the raw ptrs while they're live.
+        // Thus, entering this block requires all values to use being already ready:
+        // 0. idxs we want to write to, which are used to construct the mask.
+        // 1. enable, which depends on an initial &'a [T] and the idxs.
+        // 2. actual values to scatter (self).
+        // 3. &mut [T] which will become our base ptr.
+        unsafe {
+            // Now Entering ☢️ *mut T Zone
+            let base_ptr = crate::simd::ptr::SimdMutPtr::splat(slice.as_mut_ptr());
+            // Ferris forgive me, I have done pointer arithmetic here.
+            let ptrs = base_ptr.wrapping_add(idxs);
+            // The ptrs have been bounds-masked to prevent memory-unsafe writes insha'allah
+            intrinsics::simd_scatter(self, ptrs, enable.to_int())
+            // Cleared ☢️ *mut T Zone
+        }
+    }
+}
+
+impl<T, const LANES: usize> Copy for Simd<T, LANES>
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+}
+
+impl<T, const LANES: usize> Clone for Simd<T, LANES>
+where
+    T: SimdElement,
+    LaneCount<LANES>: SupportedLaneCount,
+{
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<T, const LANES: usize> Default for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement + Default,
+{
+    #[inline]
+    fn default() -> Self {
+        Self::splat(T::default())
+    }
+}
+
+impl<T, const LANES: usize> PartialEq for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement + PartialEq,
+{
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        // TODO use SIMD equality
+        self.to_array() == other.to_array()
+    }
+}
+
+impl<T, const LANES: usize> PartialOrd for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement + PartialOrd,
+{
+    #[inline]
+    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+        // TODO use SIMD equality
+        self.to_array().partial_cmp(other.as_ref())
+    }
+}
+
+impl<T, const LANES: usize> Eq for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement + Eq,
+{
+}
+
+impl<T, const LANES: usize> Ord for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement + Ord,
+{
+    #[inline]
+    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+        // TODO use SIMD equality
+        self.to_array().cmp(other.as_ref())
+    }
+}
+
+impl<T, const LANES: usize> core::hash::Hash for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement + core::hash::Hash,
+{
+    #[inline]
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: core::hash::Hasher,
+    {
+        self.as_array().hash(state)
+    }
+}
+
+// array references
+impl<T, const LANES: usize> AsRef<[T; LANES]> for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement,
+{
+    #[inline]
+    fn as_ref(&self) -> &[T; LANES] {
+        &self.0
+    }
+}
+
+impl<T, const LANES: usize> AsMut<[T; LANES]> for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement,
+{
+    #[inline]
+    fn as_mut(&mut self) -> &mut [T; LANES] {
+        &mut self.0
+    }
+}
+
+// slice references
+impl<T, const LANES: usize> AsRef<[T]> for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement,
+{
+    #[inline]
+    fn as_ref(&self) -> &[T] {
+        &self.0
+    }
+}
+
+impl<T, const LANES: usize> AsMut<[T]> for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement,
+{
+    #[inline]
+    fn as_mut(&mut self) -> &mut [T] {
+        &mut self.0
+    }
+}
+
+// vector/array conversion
+impl<T, const LANES: usize> From<[T; LANES]> for Simd<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement,
+{
+    fn from(array: [T; LANES]) -> Self {
+        Self(array)
+    }
+}
+
+impl<T, const LANES: usize> From<Simd<T, LANES>> for [T; LANES]
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: SimdElement,
+{
+    fn from(vector: Simd<T, LANES>) -> Self {
+        vector.to_array()
+    }
+}
+
+mod sealed {
+    pub trait Sealed {}
+}
+use sealed::Sealed;
+
+/// Marker trait for types that may be used as SIMD vector elements.
+/// SAFETY: This trait, when implemented, asserts the compiler can monomorphize
+/// `#[repr(simd)]` structs with the marked type as an element.
+/// Strictly, it is valid to impl if the vector will not be miscompiled.
+/// Practically, it is user-unfriendly to impl it if the vector won't compile,
+/// even when no soundness guarantees are broken by allowing the user to try.
+pub unsafe trait SimdElement: Sealed + Copy {
+    /// The mask element type corresponding to this element type.
+    type Mask: MaskElement;
+}
+
+impl Sealed for u8 {}
+unsafe impl SimdElement for u8 {
+    type Mask = i8;
+}
+
+impl Sealed for u16 {}
+unsafe impl SimdElement for u16 {
+    type Mask = i16;
+}
+
+impl Sealed for u32 {}
+unsafe impl SimdElement for u32 {
+    type Mask = i32;
+}
+
+impl Sealed for u64 {}
+unsafe impl SimdElement for u64 {
+    type Mask = i64;
+}
+
+impl Sealed for usize {}
+unsafe impl SimdElement for usize {
+    type Mask = isize;
+}
+
+impl Sealed for i8 {}
+unsafe impl SimdElement for i8 {
+    type Mask = i8;
+}
+
+impl Sealed for i16 {}
+unsafe impl SimdElement for i16 {
+    type Mask = i16;
+}
+
+impl Sealed for i32 {}
+unsafe impl SimdElement for i32 {
+    type Mask = i32;
+}
+
+impl Sealed for i64 {}
+unsafe impl SimdElement for i64 {
+    type Mask = i64;
+}
+
+impl Sealed for isize {}
+unsafe impl SimdElement for isize {
+    type Mask = isize;
+}
+
+impl Sealed for f32 {}
+unsafe impl SimdElement for f32 {
+    type Mask = i32;
+}
+
+impl Sealed for f64 {}
+unsafe impl SimdElement for f64 {
+    type Mask = i64;
+}
diff --git a/library/portable-simd/crates/core_simd/src/vector/float.rs b/library/portable-simd/crates/core_simd/src/vector/float.rs
new file mode 100644 (file)
index 0000000..c09d0ac
--- /dev/null
@@ -0,0 +1,210 @@
+#![allow(non_camel_case_types)]
+
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount};
+
+/// Implements inherent methods for a float vector containing multiple
+/// `$lanes` of float `$type`, which uses `$bits_ty` as its binary
+/// representation.
+macro_rules! impl_float_vector {
+    { $type:ty, $bits_ty:ty, $mask_ty:ty } => {
+        impl<const LANES: usize> Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            /// Raw transmutation to an unsigned integer vector type with the
+            /// same size and number of lanes.
+            #[inline]
+            pub fn to_bits(self) -> Simd<$bits_ty, LANES> {
+                assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Simd<$bits_ty, LANES>>());
+                unsafe { core::mem::transmute_copy(&self) }
+            }
+
+            /// Raw transmutation from an unsigned integer vector type with the
+            /// same size and number of lanes.
+            #[inline]
+            pub fn from_bits(bits: Simd<$bits_ty, LANES>) -> Self {
+                assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Simd<$bits_ty, LANES>>());
+                unsafe { core::mem::transmute_copy(&bits) }
+            }
+
+            /// Produces a vector where every lane has the absolute value of the
+            /// equivalently-indexed lane in `self`.
+            #[inline]
+            pub fn abs(self) -> Self {
+                unsafe { intrinsics::simd_fabs(self) }
+            }
+
+            /// Fused multiply-add.  Computes `(self * a) + b` with only one rounding error,
+            /// yielding a more accurate result than an unfused multiply-add.
+            ///
+            /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target
+            /// architecture has a dedicated `fma` CPU instruction.  However, this is not always
+            /// true, and will be heavily dependent on designing algorithms with specific target
+            /// hardware in mind.
+            #[cfg(feature = "std")]
+            #[inline]
+            pub fn mul_add(self, a: Self, b: Self) -> Self {
+                unsafe { intrinsics::simd_fma(self, a, b) }
+            }
+
+            /// Produces a vector where every lane has the square root value
+            /// of the equivalently-indexed lane in `self`
+            #[inline]
+            #[cfg(feature = "std")]
+            pub fn sqrt(self) -> Self {
+                unsafe { intrinsics::simd_fsqrt(self) }
+            }
+
+            /// Takes the reciprocal (inverse) of each lane, `1/x`.
+            #[inline]
+            pub fn recip(self) -> Self {
+                Self::splat(1.0) / self
+            }
+
+            /// Converts each lane from radians to degrees.
+            #[inline]
+            pub fn to_degrees(self) -> Self {
+                // to_degrees uses a special constant for better precision, so extract that constant
+                self * Self::splat(<$type>::to_degrees(1.))
+            }
+
+            /// Converts each lane from degrees to radians.
+            #[inline]
+            pub fn to_radians(self) -> Self {
+                self * Self::splat(<$type>::to_radians(1.))
+            }
+
+            /// Returns true for each lane if it has a positive sign, including
+            /// `+0.0`, `NaN`s with positive sign bit and positive infinity.
+            #[inline]
+            pub fn is_sign_positive(self) -> Mask<$mask_ty, LANES> {
+                !self.is_sign_negative()
+            }
+
+            /// Returns true for each lane if it has a negative sign, including
+            /// `-0.0`, `NaN`s with negative sign bit and negative infinity.
+            #[inline]
+            pub fn is_sign_negative(self) -> Mask<$mask_ty, LANES> {
+                let sign_bits = self.to_bits() & Simd::splat((!0 >> 1) + 1);
+                sign_bits.lanes_gt(Simd::splat(0))
+            }
+
+            /// Returns true for each lane if its value is `NaN`.
+            #[inline]
+            pub fn is_nan(self) -> Mask<$mask_ty, LANES> {
+                self.lanes_ne(self)
+            }
+
+            /// Returns true for each lane if its value is positive infinity or negative infinity.
+            #[inline]
+            pub fn is_infinite(self) -> Mask<$mask_ty, LANES> {
+                self.abs().lanes_eq(Self::splat(<$type>::INFINITY))
+            }
+
+            /// Returns true for each lane if its value is neither infinite nor `NaN`.
+            #[inline]
+            pub fn is_finite(self) -> Mask<$mask_ty, LANES> {
+                self.abs().lanes_lt(Self::splat(<$type>::INFINITY))
+            }
+
+            /// Returns true for each lane if its value is subnormal.
+            #[inline]
+            pub fn is_subnormal(self) -> Mask<$mask_ty, LANES> {
+                self.abs().lanes_ne(Self::splat(0.0)) & (self.to_bits() & Self::splat(<$type>::INFINITY).to_bits()).lanes_eq(Simd::splat(0))
+            }
+
+            /// Returns true for each lane if its value is neither neither zero, infinite,
+            /// subnormal, or `NaN`.
+            #[inline]
+            pub fn is_normal(self) -> Mask<$mask_ty, LANES> {
+                !(self.abs().lanes_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite())
+            }
+
+            /// Replaces each lane with a number that represents its sign.
+            ///
+            /// * `1.0` if the number is positive, `+0.0`, or `INFINITY`
+            /// * `-1.0` if the number is negative, `-0.0`, or `NEG_INFINITY`
+            /// * `NAN` if the number is `NAN`
+            #[inline]
+            pub fn signum(self) -> Self {
+                self.is_nan().select(Self::splat(<$type>::NAN), Self::splat(1.0).copysign(self))
+            }
+
+            /// Returns each lane with the magnitude of `self` and the sign of `sign`.
+            ///
+            /// If any lane is a `NAN`, then a `NAN` with the sign of `sign` is returned.
+            #[inline]
+            pub fn copysign(self, sign: Self) -> Self {
+                let sign_bit = sign.to_bits() & Self::splat(-0.).to_bits();
+                let magnitude = self.to_bits() & !Self::splat(-0.).to_bits();
+                Self::from_bits(sign_bit | magnitude)
+            }
+
+            /// Returns the minimum of each lane.
+            ///
+            /// If one of the values is `NAN`, then the other value is returned.
+            #[inline]
+            pub fn min(self, other: Self) -> Self {
+                // TODO consider using an intrinsic
+                self.is_nan().select(
+                    other,
+                    self.lanes_ge(other).select(other, self)
+                )
+            }
+
+            /// Returns the maximum of each lane.
+            ///
+            /// If one of the values is `NAN`, then the other value is returned.
+            #[inline]
+            pub fn max(self, other: Self) -> Self {
+                // TODO consider using an intrinsic
+                self.is_nan().select(
+                    other,
+                    self.lanes_le(other).select(other, self)
+                )
+            }
+
+            /// Restrict each lane to a certain interval unless it is NaN.
+            ///
+            /// For each lane in `self`, returns the corresponding lane in `max` if the lane is
+            /// greater than `max`, and the corresponding lane in `min` if the lane is less
+            /// than `min`.  Otherwise returns the lane in `self`.
+            #[inline]
+            pub fn clamp(self, min: Self, max: Self) -> Self {
+                assert!(
+                    min.lanes_le(max).all(),
+                    "each lane in `min` must be less than or equal to the corresponding lane in `max`",
+                );
+                let mut x = self;
+                x = x.lanes_lt(min).select(min, x);
+                x = x.lanes_gt(max).select(max, x);
+                x
+            }
+        }
+    };
+}
+
+impl_float_vector! { f32, u32, i32 }
+impl_float_vector! { f64, u64, i64 }
+
+/// Vector of two `f32` values
+pub type f32x2 = Simd<f32, 2>;
+
+/// Vector of four `f32` values
+pub type f32x4 = Simd<f32, 4>;
+
+/// Vector of eight `f32` values
+pub type f32x8 = Simd<f32, 8>;
+
+/// Vector of 16 `f32` values
+pub type f32x16 = Simd<f32, 16>;
+
+/// Vector of two `f64` values
+pub type f64x2 = Simd<f64, 2>;
+
+/// Vector of four `f64` values
+pub type f64x4 = Simd<f64, 4>;
+
+/// Vector of eight `f64` values
+pub type f64x8 = Simd<f64, 8>;
diff --git a/library/portable-simd/crates/core_simd/src/vector/int.rs b/library/portable-simd/crates/core_simd/src/vector/int.rs
new file mode 100644 (file)
index 0000000..3eac02a
--- /dev/null
@@ -0,0 +1,103 @@
+#![allow(non_camel_case_types)]
+
+use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount};
+
+/// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`.
+macro_rules! impl_integer_vector {
+    { $type:ty } => {
+        impl<const LANES: usize> Simd<$type, LANES>
+        where
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            /// Returns true for each positive lane and false if it is zero or negative.
+            #[inline]
+            pub fn is_positive(self) -> Mask<$type, LANES> {
+                self.lanes_gt(Self::splat(0))
+            }
+
+            /// Returns true for each negative lane and false if it is zero or positive.
+            #[inline]
+            pub fn is_negative(self) -> Mask<$type, LANES> {
+                self.lanes_lt(Self::splat(0))
+            }
+
+            /// Returns numbers representing the sign of each lane.
+            /// * `0` if the number is zero
+            /// * `1` if the number is positive
+            /// * `-1` if the number is negative
+            #[inline]
+            pub fn signum(self) -> Self {
+                self.is_positive().select(
+                    Self::splat(1),
+                    self.is_negative().select(Self::splat(-1), Self::splat(0))
+                )
+            }
+        }
+    }
+}
+
+impl_integer_vector! { isize }
+impl_integer_vector! { i16 }
+impl_integer_vector! { i32 }
+impl_integer_vector! { i64 }
+impl_integer_vector! { i8 }
+
+/// Vector of two `isize` values
+pub type isizex2 = Simd<isize, 2>;
+
+/// Vector of four `isize` values
+pub type isizex4 = Simd<isize, 4>;
+
+/// Vector of eight `isize` values
+pub type isizex8 = Simd<isize, 8>;
+
+/// Vector of two `i16` values
+pub type i16x2 = Simd<i16, 2>;
+
+/// Vector of four `i16` values
+pub type i16x4 = Simd<i16, 4>;
+
+/// Vector of eight `i16` values
+pub type i16x8 = Simd<i16, 8>;
+
+/// Vector of 16 `i16` values
+pub type i16x16 = Simd<i16, 16>;
+
+/// Vector of 32 `i16` values
+pub type i16x32 = Simd<i16, 32>;
+
+/// Vector of two `i32` values
+pub type i32x2 = Simd<i32, 2>;
+
+/// Vector of four `i32` values
+pub type i32x4 = Simd<i32, 4>;
+
+/// Vector of eight `i32` values
+pub type i32x8 = Simd<i32, 8>;
+
+/// Vector of 16 `i32` values
+pub type i32x16 = Simd<i32, 16>;
+
+/// Vector of two `i64` values
+pub type i64x2 = Simd<i64, 2>;
+
+/// Vector of four `i64` values
+pub type i64x4 = Simd<i64, 4>;
+
+/// Vector of eight `i64` values
+pub type i64x8 = Simd<i64, 8>;
+
+/// Vector of four `i8` values
+pub type i8x4 = Simd<i8, 4>;
+
+/// Vector of eight `i8` values
+pub type i8x8 = Simd<i8, 8>;
+
+/// Vector of 16 `i8` values
+pub type i8x16 = Simd<i8, 16>;
+
+/// Vector of 32 `i8` values
+pub type i8x32 = Simd<i8, 32>;
+
+/// Vector of 64 `i8` values
+pub type i8x64 = Simd<i8, 64>;
diff --git a/library/portable-simd/crates/core_simd/src/vector/ptr.rs b/library/portable-simd/crates/core_simd/src/vector/ptr.rs
new file mode 100644 (file)
index 0000000..ac9b98c
--- /dev/null
@@ -0,0 +1,55 @@
+//! Private implementation details of public gather/scatter APIs.
+use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+use core::mem;
+
+/// A vector of *const T.
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+pub(crate) struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
+
+impl<T, const LANES: usize> SimdConstPtr<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: Sized,
+{
+    #[inline]
+    #[must_use]
+    pub fn splat(ptr: *const T) -> Self {
+        Self([ptr; LANES])
+    }
+
+    #[inline]
+    #[must_use]
+    pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
+        unsafe {
+            let x: Simd<usize, LANES> = mem::transmute_copy(&self);
+            mem::transmute_copy(&{ x + (addend * mem::size_of::<T>()) })
+        }
+    }
+}
+
+/// A vector of *mut T. Be very careful around potential aliasing.
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+pub(crate) struct SimdMutPtr<T, const LANES: usize>([*mut T; LANES]);
+
+impl<T, const LANES: usize> SimdMutPtr<T, LANES>
+where
+    LaneCount<LANES>: SupportedLaneCount,
+    T: Sized,
+{
+    #[inline]
+    #[must_use]
+    pub fn splat(ptr: *mut T) -> Self {
+        Self([ptr; LANES])
+    }
+
+    #[inline]
+    #[must_use]
+    pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
+        unsafe {
+            let x: Simd<usize, LANES> = mem::transmute_copy(&self);
+            mem::transmute_copy(&{ x + (addend * mem::size_of::<T>()) })
+        }
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/src/vector/uint.rs b/library/portable-simd/crates/core_simd/src/vector/uint.rs
new file mode 100644 (file)
index 0000000..ed91fc3
--- /dev/null
@@ -0,0 +1,63 @@
+#![allow(non_camel_case_types)]
+
+use crate::simd::Simd;
+
+/// Vector of two `usize` values
+pub type usizex2 = Simd<usize, 2>;
+
+/// Vector of four `usize` values
+pub type usizex4 = Simd<usize, 4>;
+
+/// Vector of eight `usize` values
+pub type usizex8 = Simd<usize, 8>;
+
+/// Vector of two `u16` values
+pub type u16x2 = Simd<u16, 2>;
+
+/// Vector of four `u16` values
+pub type u16x4 = Simd<u16, 4>;
+
+/// Vector of eight `u16` values
+pub type u16x8 = Simd<u16, 8>;
+
+/// Vector of 16 `u16` values
+pub type u16x16 = Simd<u16, 16>;
+
+/// Vector of 32 `u16` values
+pub type u16x32 = Simd<u16, 32>;
+
+/// Vector of two `u32` values
+pub type u32x2 = Simd<u32, 2>;
+
+/// Vector of four `u32` values
+pub type u32x4 = Simd<u32, 4>;
+
+/// Vector of eight `u32` values
+pub type u32x8 = Simd<u32, 8>;
+
+/// Vector of 16 `u32` values
+pub type u32x16 = Simd<u32, 16>;
+
+/// Vector of two `u64` values
+pub type u64x2 = Simd<u64, 2>;
+
+/// Vector of four `u64` values
+pub type u64x4 = Simd<u64, 4>;
+
+/// Vector of eight `u64` values
+pub type u64x8 = Simd<u64, 8>;
+
+/// Vector of four `u8` values
+pub type u8x4 = Simd<u8, 4>;
+
+/// Vector of eight `u8` values
+pub type u8x8 = Simd<u8, 8>;
+
+/// Vector of 16 `u8` values
+pub type u8x16 = Simd<u8, 16>;
+
+/// Vector of 32 `u8` values
+pub type u8x32 = Simd<u8, 32>;
+
+/// Vector of 64 `u8` values
+pub type u8x64 = Simd<u8, 64>;
diff --git a/library/portable-simd/crates/core_simd/src/vendor.rs b/library/portable-simd/crates/core_simd/src/vendor.rs
new file mode 100644 (file)
index 0000000..e8ce717
--- /dev/null
@@ -0,0 +1,29 @@
+/// Provides implementations of `From<$a> for $b` and `From<$b> for $a` that transmutes the value.
+#[allow(unused)]
+macro_rules! from_transmute {
+    { unsafe $a:ty => $b:ty } => {
+        from_transmute!{ @impl $a => $b }
+        from_transmute!{ @impl $b => $a }
+    };
+    { @impl $from:ty => $to:ty } => {
+        impl core::convert::From<$from> for $to {
+            #[inline]
+            fn from(value: $from) -> $to {
+                unsafe { core::mem::transmute(value) }
+            }
+        }
+    };
+}
+
+/// Conversions to x86's SIMD types.
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+mod x86;
+
+#[cfg(any(target_arch = "wasm32"))]
+mod wasm32;
+
+#[cfg(any(target_arch = "aarch64", target_arch = "arm",))]
+mod arm;
+
+#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
+mod powerpc;
diff --git a/library/portable-simd/crates/core_simd/src/vendor/arm.rs b/library/portable-simd/crates/core_simd/src/vendor/arm.rs
new file mode 100644 (file)
index 0000000..ff3b69c
--- /dev/null
@@ -0,0 +1,76 @@
+#![allow(unused)]
+use crate::simd::*;
+
+#[cfg(target_arch = "arm")]
+use core::arch::arm::*;
+
+#[cfg(target_arch = "aarch64")]
+use core::arch::aarch64::*;
+
+#[cfg(any(
+    target_arch = "aarch64",
+    all(target_arch = "arm", target_feature = "v7"),
+))]
+mod neon {
+    use super::*;
+
+    from_transmute! { unsafe f32x2 => float32x2_t }
+    from_transmute! { unsafe f32x4 => float32x4_t }
+
+    from_transmute! { unsafe u8x8 => uint8x8_t }
+    from_transmute! { unsafe u8x16 => uint8x16_t }
+    from_transmute! { unsafe i8x8 => int8x8_t }
+    from_transmute! { unsafe i8x16 => int8x16_t }
+    from_transmute! { unsafe u8x8 => poly8x8_t }
+    from_transmute! { unsafe u8x16 => poly8x16_t }
+
+    from_transmute! { unsafe u16x4 => uint16x4_t }
+    from_transmute! { unsafe u16x8 => uint16x8_t }
+    from_transmute! { unsafe i16x4 => int16x4_t }
+    from_transmute! { unsafe i16x8 => int16x8_t }
+    from_transmute! { unsafe u16x4 => poly16x4_t }
+    from_transmute! { unsafe u16x8 => poly16x8_t }
+
+    from_transmute! { unsafe u32x2 => uint32x2_t }
+    from_transmute! { unsafe u32x4 => uint32x4_t }
+    from_transmute! { unsafe i32x2 => int32x2_t }
+    from_transmute! { unsafe i32x4 => int32x4_t }
+
+    from_transmute! { unsafe Simd<u64, 1> => uint64x1_t }
+    from_transmute! { unsafe u64x2 => uint64x2_t }
+    from_transmute! { unsafe Simd<i64, 1> => int64x1_t }
+    from_transmute! { unsafe i64x2 => int64x2_t }
+    from_transmute! { unsafe Simd<u64, 1> => poly64x1_t }
+    from_transmute! { unsafe u64x2 => poly64x2_t }
+}
+
+#[cfg(any(
+    all(target_feature = "v5te", not(target_feature = "mclass")),
+    all(target_feature = "mclass", target_feature = "dsp"),
+))]
+mod dsp {
+    use super::*;
+
+    from_transmute! { unsafe Simd<u16, 2> => uint16x2_t }
+    from_transmute! { unsafe Simd<i16, 2> => int16x2_t }
+}
+
+#[cfg(any(
+    all(target_feature = "v6", not(target_feature = "mclass")),
+    all(target_feature = "mclass", target_feature = "dsp"),
+))]
+mod simd32 {
+    use super::*;
+
+    from_transmute! { unsafe Simd<u8, 4> => uint8x4_t }
+    from_transmute! { unsafe Simd<i8, 4> => int8x4_t }
+}
+
+#[cfg(target_arch = "aarch64")]
+mod aarch64 {
+    use super::neon::*;
+    use super::*;
+
+    from_transmute! { unsafe Simd<f64, 1> => float64x1_t }
+    from_transmute! { unsafe f64x2 => float64x2_t }
+}
diff --git a/library/portable-simd/crates/core_simd/src/vendor/powerpc.rs b/library/portable-simd/crates/core_simd/src/vendor/powerpc.rs
new file mode 100644 (file)
index 0000000..92f97d4
--- /dev/null
@@ -0,0 +1,11 @@
+use crate::simd::*;
+
+#[cfg(target_arch = "powerpc")]
+use core::arch::powerpc::*;
+
+#[cfg(target_arch = "powerpc64")]
+use core::arch::powerpc64::*;
+
+from_transmute! { unsafe f64x2 => vector_double }
+from_transmute! { unsafe i64x2 => vector_signed_long }
+from_transmute! { unsafe u64x2 => vector_unsigned_long }
diff --git a/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs b/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs
new file mode 100644 (file)
index 0000000..ef3baf8
--- /dev/null
@@ -0,0 +1,30 @@
+use crate::simd::*;
+use core::arch::wasm32::v128;
+
+from_transmute! { unsafe u8x16 => v128 }
+from_transmute! { unsafe i8x16 => v128 }
+
+from_transmute! { unsafe u16x8 => v128 }
+from_transmute! { unsafe i16x8 => v128 }
+
+from_transmute! { unsafe u32x4 => v128 }
+from_transmute! { unsafe i32x4 => v128 }
+from_transmute! { unsafe f32x4 => v128 }
+
+from_transmute! { unsafe u64x2 => v128 }
+from_transmute! { unsafe i64x2 => v128 }
+from_transmute! { unsafe f64x2 => v128 }
+
+#[cfg(target_pointer_width = "32")]
+mod p32 {
+    use super::*;
+    from_transmute! { unsafe usizex4 => v128 }
+    from_transmute! { unsafe isizex4 => v128 }
+}
+
+#[cfg(target_pointer_width = "64")]
+mod p64 {
+    use super::*;
+    from_transmute! { unsafe usizex2 => v128 }
+    from_transmute! { unsafe isizex2 => v128 }
+}
diff --git a/library/portable-simd/crates/core_simd/src/vendor/x86.rs b/library/portable-simd/crates/core_simd/src/vendor/x86.rs
new file mode 100644 (file)
index 0000000..d3c19cc
--- /dev/null
@@ -0,0 +1,63 @@
+use crate::simd::*;
+
+#[cfg(any(target_arch = "x86"))]
+use core::arch::x86::*;
+
+#[cfg(target_arch = "x86_64")]
+use core::arch::x86_64::*;
+
+from_transmute! { unsafe u8x16 => __m128i }
+from_transmute! { unsafe u8x32 => __m256i }
+//from_transmute! { unsafe u8x64 => __m512i }
+from_transmute! { unsafe i8x16 => __m128i }
+from_transmute! { unsafe i8x32 => __m256i }
+//from_transmute! { unsafe i8x64 => __m512i }
+
+from_transmute! { unsafe u16x8 => __m128i }
+from_transmute! { unsafe u16x16 => __m256i }
+from_transmute! { unsafe u16x32 => __m512i }
+from_transmute! { unsafe i16x8 => __m128i }
+from_transmute! { unsafe i16x16 => __m256i }
+from_transmute! { unsafe i16x32 => __m512i }
+
+from_transmute! { unsafe u32x4 => __m128i }
+from_transmute! { unsafe u32x8 => __m256i }
+from_transmute! { unsafe u32x16 => __m512i }
+from_transmute! { unsafe i32x4 => __m128i }
+from_transmute! { unsafe i32x8 => __m256i }
+from_transmute! { unsafe i32x16 => __m512i }
+from_transmute! { unsafe f32x4 => __m128 }
+from_transmute! { unsafe f32x8 => __m256 }
+from_transmute! { unsafe f32x16 => __m512 }
+
+from_transmute! { unsafe u64x2 => __m128i }
+from_transmute! { unsafe u64x4 => __m256i }
+from_transmute! { unsafe u64x8 => __m512i }
+from_transmute! { unsafe i64x2 => __m128i }
+from_transmute! { unsafe i64x4 => __m256i }
+from_transmute! { unsafe i64x8 => __m512i }
+from_transmute! { unsafe f64x2 => __m128d }
+from_transmute! { unsafe f64x4 => __m256d }
+from_transmute! { unsafe f64x8 => __m512d }
+
+#[cfg(target_pointer_width = "32")]
+mod p32 {
+    use super::*;
+    from_transmute! { unsafe usizex4 => __m128i }
+    from_transmute! { unsafe usizex8 => __m256i }
+    from_transmute! { unsafe Simd<usize, 16> => __m512i }
+    from_transmute! { unsafe isizex4 => __m128i }
+    from_transmute! { unsafe isizex8 => __m256i }
+    from_transmute! { unsafe Simd<isize, 16> => __m512i }
+}
+
+#[cfg(target_pointer_width = "64")]
+mod p64 {
+    use super::*;
+    from_transmute! { unsafe usizex2 => __m128i }
+    from_transmute! { unsafe usizex4 => __m256i }
+    from_transmute! { unsafe usizex8 => __m512i }
+    from_transmute! { unsafe isizex2 => __m128i }
+    from_transmute! { unsafe isizex4 => __m256i }
+    from_transmute! { unsafe isizex8 => __m512i }
+}
diff --git a/library/portable-simd/crates/core_simd/tests/f32_ops.rs b/library/portable-simd/crates/core_simd/tests/f32_ops.rs
new file mode 100644 (file)
index 0000000..414a832
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_float_tests! { f32, i32 }
diff --git a/library/portable-simd/crates/core_simd/tests/f64_ops.rs b/library/portable-simd/crates/core_simd/tests/f64_ops.rs
new file mode 100644 (file)
index 0000000..e0a1fa3
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_float_tests! { f64, i64 }
diff --git a/library/portable-simd/crates/core_simd/tests/i16_ops.rs b/library/portable-simd/crates/core_simd/tests/i16_ops.rs
new file mode 100644 (file)
index 0000000..f6c5d74
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_signed_tests! { i16 }
diff --git a/library/portable-simd/crates/core_simd/tests/i32_ops.rs b/library/portable-simd/crates/core_simd/tests/i32_ops.rs
new file mode 100644 (file)
index 0000000..69a831c
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_signed_tests! { i32 }
diff --git a/library/portable-simd/crates/core_simd/tests/i64_ops.rs b/library/portable-simd/crates/core_simd/tests/i64_ops.rs
new file mode 100644 (file)
index 0000000..37ac081
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_signed_tests! { i64 }
diff --git a/library/portable-simd/crates/core_simd/tests/i8_ops.rs b/library/portable-simd/crates/core_simd/tests/i8_ops.rs
new file mode 100644 (file)
index 0000000..11e4a5c
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_signed_tests! { i8 }
diff --git a/library/portable-simd/crates/core_simd/tests/isize_ops.rs b/library/portable-simd/crates/core_simd/tests/isize_ops.rs
new file mode 100644 (file)
index 0000000..5cc9de2
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_signed_tests! { isize }
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops.rs b/library/portable-simd/crates/core_simd/tests/mask_ops.rs
new file mode 100644 (file)
index 0000000..f113b50
--- /dev/null
@@ -0,0 +1,3 @@
+#![feature(portable_simd)]
+
+mod mask_ops_impl;
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask16.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask16.rs
new file mode 100644 (file)
index 0000000..0fe82fa
--- /dev/null
@@ -0,0 +1,4 @@
+mask_tests! { mask16x4, 4 }
+mask_tests! { mask16x8, 8 }
+mask_tests! { mask16x16, 16 }
+mask_tests! { mask16x32, 32 }
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask32.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask32.rs
new file mode 100644 (file)
index 0000000..66d987a
--- /dev/null
@@ -0,0 +1,4 @@
+mask_tests! { mask32x2, 2 }
+mask_tests! { mask32x4, 4 }
+mask_tests! { mask32x8, 8 }
+mask_tests! { mask32x16, 16 }
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask64.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask64.rs
new file mode 100644 (file)
index 0000000..a1f1f67
--- /dev/null
@@ -0,0 +1,3 @@
+mask_tests! { mask64x2, 2 }
+mask_tests! { mask64x4, 4 }
+mask_tests! { mask64x8, 8 }
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask8.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask8.rs
new file mode 100644 (file)
index 0000000..9c06fbc
--- /dev/null
@@ -0,0 +1,3 @@
+mask_tests! { mask8x8, 8 }
+mask_tests! { mask8x16, 16 }
+mask_tests! { mask8x32, 32 }
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mask_macros.rs
new file mode 100644 (file)
index 0000000..795f9e2
--- /dev/null
@@ -0,0 +1,225 @@
+macro_rules! mask_tests {
+    { $vector:ident, $lanes:literal } => {
+        #[cfg(test)]
+        mod $vector {
+            use core_simd::$vector as Vector;
+            const LANES: usize = $lanes;
+
+            #[cfg(target_arch = "wasm32")]
+            use wasm_bindgen_test::*;
+
+            #[cfg(target_arch = "wasm32")]
+            wasm_bindgen_test_configure!(run_in_browser);
+
+            fn from_slice(slice: &[bool]) -> Vector {
+                let mut value = Vector::default();
+                for (i, b) in slice.iter().take(LANES).enumerate() {
+                    value.set(i, *b);
+                }
+                value
+            }
+
+            fn apply_unary_lanewise(x: Vector, f: impl Fn(bool) -> bool) -> Vector {
+                let mut value = Vector::default();
+                for i in 0..LANES {
+                    value.set(i, f(x.test(i)));
+                }
+                value
+            }
+
+            fn apply_binary_lanewise(x: Vector, y: Vector, f: impl Fn(bool, bool) -> bool) -> Vector {
+                let mut value = Vector::default();
+                for i in 0..LANES {
+                    value.set(i, f(x.test(i), y.test(i)));
+                }
+                value
+            }
+
+            fn apply_binary_scalar_lhs_lanewise(x: bool, mut y: Vector, f: impl Fn(bool, bool) -> bool) -> Vector {
+                for i in 0..LANES {
+                    y.set(i, f(x, y.test(i)));
+                }
+                y
+            }
+
+            fn apply_binary_scalar_rhs_lanewise(mut x: Vector, y: bool, f: impl Fn(bool, bool) -> bool) -> Vector {
+                for i in 0..LANES {
+                    x.set(i, f(x.test(i), y));
+                }
+                x
+            }
+
+            const A: [bool; 64] = [
+                false, true, false, true, false, false, true, true,
+                false, true, false, true, false, false, true, true,
+                false, true, false, true, false, false, true, true,
+                false, true, false, true, false, false, true, true,
+                false, true, false, true, false, false, true, true,
+                false, true, false, true, false, false, true, true,
+                false, true, false, true, false, false, true, true,
+                false, true, false, true, false, false, true, true,
+            ];
+            const B: [bool; 64] = [
+                false, false, true, true, false, true, false, true,
+                false, false, true, true, false, true, false, true,
+                false, false, true, true, false, true, false, true,
+                false, false, true, true, false, true, false, true,
+                false, false, true, true, false, true, false, true,
+                false, false, true, true, false, true, false, true,
+                false, false, true, true, false, true, false, true,
+                false, false, true, true, false, true, false, true,
+            ];
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitand() {
+                let a = from_slice(&A);
+                let b = from_slice(&B);
+                let expected = apply_binary_lanewise(a, b, core::ops::BitAnd::bitand);
+                assert_eq!(a & b, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitand_assign() {
+                let mut a = from_slice(&A);
+                let b = from_slice(&B);
+                let expected = apply_binary_lanewise(a, b, core::ops::BitAnd::bitand);
+                a &= b;
+                assert_eq!(a, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitand_scalar_rhs() {
+                let a = from_slice(&A);
+                let expected = a;
+                assert_eq!(a & true, expected);
+                assert_eq!(a & false, Vector::splat(false));
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitand_scalar_lhs() {
+                let a = from_slice(&A);
+                let expected = a;
+                assert_eq!(true & a, expected);
+                assert_eq!(false & a, Vector::splat(false));
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitand_assign_scalar() {
+                let mut a = from_slice(&A);
+                let expected = a;
+                a &= true;
+                assert_eq!(a, expected);
+                a &= false;
+                assert_eq!(a, Vector::splat(false));
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitor() {
+                let a = from_slice(&A);
+                let b = from_slice(&B);
+                let expected = apply_binary_lanewise(a, b, core::ops::BitOr::bitor);
+                assert_eq!(a | b, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitor_assign() {
+                let mut a = from_slice(&A);
+                let b = from_slice(&B);
+                let expected = apply_binary_lanewise(a, b, core::ops::BitOr::bitor);
+                a |= b;
+                assert_eq!(a, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitor_scalar_rhs() {
+                let a = from_slice(&A);
+                assert_eq!(a | false, a);
+                assert_eq!(a | true, Vector::splat(true));
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitor_scalar_lhs() {
+                let a = from_slice(&A);
+                assert_eq!(false | a, a);
+                assert_eq!(true | a, Vector::splat(true));
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitor_assign_scalar() {
+                let mut a = from_slice(&A);
+                let expected = a;
+                a |= false;
+                assert_eq!(a, expected);
+                a |= true;
+                assert_eq!(a, Vector::splat(true));
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitxor() {
+                let a = from_slice(&A);
+                let b = from_slice(&B);
+                let expected = apply_binary_lanewise(a, b, core::ops::BitXor::bitxor);
+                assert_eq!(a ^ b, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitxor_assign() {
+                let mut a = from_slice(&A);
+                let b = from_slice(&B);
+                let expected = apply_binary_lanewise(a, b, core::ops::BitXor::bitxor);
+                a ^= b;
+                assert_eq!(a, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitxor_scalar_rhs() {
+                let a = from_slice(&A);
+                let expected = apply_binary_scalar_rhs_lanewise(a, true, core::ops::BitXor::bitxor);
+                assert_eq!(a ^ false, a);
+                assert_eq!(a ^ true, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitxor_scalar_lhs() {
+                let a = from_slice(&A);
+                let expected = apply_binary_scalar_lhs_lanewise(true, a, core::ops::BitXor::bitxor);
+                assert_eq!(false ^ a, a);
+                assert_eq!(true ^ a, expected);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn bitxor_assign_scalar() {
+                let mut a = from_slice(&A);
+                let expected_unset = a;
+                let expected_set = apply_binary_scalar_rhs_lanewise(a, true, core::ops::BitXor::bitxor);
+                a ^= false;
+                assert_eq!(a, expected_unset);
+                a ^= true;
+                assert_eq!(a, expected_set);
+            }
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn not() {
+                let v = from_slice(&A);
+                let expected = apply_unary_lanewise(v, core::ops::Not::not);
+                assert_eq!(!v, expected);
+            }
+        }
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/masksize.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/masksize.rs
new file mode 100644 (file)
index 0000000..e0a44d8
--- /dev/null
@@ -0,0 +1,3 @@
+mask_tests! { masksizex2, 2 }
+mask_tests! { masksizex4, 4 }
+mask_tests! { masksizex8, 8 }
diff --git a/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mod.rs b/library/portable-simd/crates/core_simd/tests/mask_ops_impl/mod.rs
new file mode 100644 (file)
index 0000000..b9ec846
--- /dev/null
@@ -0,0 +1,9 @@
+#[macro_use]
+mod mask_macros;
+
+#[rustfmt::skip]
+mod mask8;
+mod mask16;
+mod mask32;
+mod mask64;
+mod masksize;
diff --git a/library/portable-simd/crates/core_simd/tests/masks.rs b/library/portable-simd/crates/core_simd/tests/masks.rs
new file mode 100644 (file)
index 0000000..6a8ecd3
--- /dev/null
@@ -0,0 +1,102 @@
+#![feature(portable_simd)]
+
+#[cfg(target_arch = "wasm32")]
+use wasm_bindgen_test::*;
+
+#[cfg(target_arch = "wasm32")]
+wasm_bindgen_test_configure!(run_in_browser);
+
+macro_rules! test_mask_api {
+    { $type:ident } => {
+        #[allow(non_snake_case)]
+        mod $type {
+            #[cfg(target_arch = "wasm32")]
+            use wasm_bindgen_test::*;
+
+            #[test]
+            #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+            fn set_and_test() {
+                let values = [true, false, false, true, false, false, true, false];
+                let mut mask = core_simd::Mask::<$type, 8>::splat(false);
+                for (lane, value) in values.iter().copied().enumerate() {
+                    mask.set(lane, value);
+                }
+                for (lane, value) in values.iter().copied().enumerate() {
+                    assert_eq!(mask.test(lane), value);
+                }
+            }
+
+            #[test]
+            #[should_panic]
+            fn set_invalid_lane() {
+                let mut mask = core_simd::Mask::<$type, 8>::splat(false);
+                mask.set(8, true);
+                let _ = mask;
+            }
+
+            #[test]
+            #[should_panic]
+            fn test_invalid_lane() {
+                let mask = core_simd::Mask::<$type, 8>::splat(false);
+                let _ = mask.test(8);
+            }
+
+            #[test]
+            fn any() {
+                assert!(!core_simd::Mask::<$type, 8>::splat(false).any());
+                assert!(core_simd::Mask::<$type, 8>::splat(true).any());
+                let mut v = core_simd::Mask::<$type, 8>::splat(false);
+                v.set(2, true);
+                assert!(v.any());
+            }
+
+            #[test]
+            fn all() {
+                assert!(!core_simd::Mask::<$type, 8>::splat(false).all());
+                assert!(core_simd::Mask::<$type, 8>::splat(true).all());
+                let mut v = core_simd::Mask::<$type, 8>::splat(false);
+                v.set(2, true);
+                assert!(!v.all());
+            }
+
+            #[test]
+            fn roundtrip_int_conversion() {
+                let values = [true, false, false, true, false, false, true, false];
+                let mask = core_simd::Mask::<$type, 8>::from_array(values);
+                let int = mask.to_int();
+                assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]);
+                assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask);
+            }
+
+            #[cfg(feature = "generic_const_exprs")]
+            #[test]
+            fn roundtrip_bitmask_conversion() {
+                let values = [
+                    true, false, false, true, false, false, true, false,
+                    true, true, false, false, false, false, false, true,
+                ];
+                let mask = core_simd::Mask::<$type, 16>::from_array(values);
+                let bitmask = mask.to_bitmask();
+                assert_eq!(bitmask, [0b01001001, 0b10000011]);
+                assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
+            }
+        }
+    }
+}
+
+mod mask_api {
+    test_mask_api! { i8 }
+    test_mask_api! { i16 }
+    test_mask_api! { i32 }
+    test_mask_api! { i64 }
+    test_mask_api! { isize }
+}
+
+#[test]
+fn convert() {
+    let values = [true, false, false, true, false, false, true, false];
+    assert_eq!(
+        core_simd::Mask::<i8, 8>::from_array(values),
+        core_simd::Mask::<i32, 8>::from_array(values).into()
+    );
+}
diff --git a/library/portable-simd/crates/core_simd/tests/ops_macros.rs b/library/portable-simd/crates/core_simd/tests/ops_macros.rs
new file mode 100644 (file)
index 0000000..31b7ee2
--- /dev/null
@@ -0,0 +1,618 @@
+/// Implements a test on a unary operation using proptest.
+///
+/// Compares the vector operation to the equivalent scalar operation.
+#[macro_export]
+macro_rules! impl_unary_op_test {
+    { $scalar:ty, $trait:ident :: $fn:ident, $scalar_fn:expr } => {
+        test_helpers::test_lanes! {
+            fn $fn<const LANES: usize>() {
+                test_helpers::test_unary_elementwise(
+                    &<core_simd::Simd<$scalar, LANES> as core::ops::$trait>::$fn,
+                    &$scalar_fn,
+                    &|_| true,
+                );
+            }
+        }
+    };
+    { $scalar:ty, $trait:ident :: $fn:ident } => {
+        impl_unary_op_test! { $scalar, $trait::$fn, <$scalar as core::ops::$trait>::$fn }
+    };
+}
+
+/// Implements a test on a binary operation using proptest.
+///
+/// Compares the vector operation to the equivalent scalar operation.
+#[macro_export]
+macro_rules! impl_binary_op_test {
+    { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr } => {
+        mod $fn {
+            use super::*;
+            use core_simd::Simd;
+
+            test_helpers::test_lanes! {
+                fn normal<const LANES: usize>() {
+                    test_helpers::test_binary_elementwise(
+                        &<Simd<$scalar, LANES> as core::ops::$trait>::$fn,
+                        &$scalar_fn,
+                        &|_, _| true,
+                    );
+                }
+
+                fn scalar_rhs<const LANES: usize>() {
+                    test_helpers::test_binary_scalar_rhs_elementwise(
+                        &<Simd<$scalar, LANES> as core::ops::$trait<$scalar>>::$fn,
+                        &$scalar_fn,
+                        &|_, _| true,
+                    );
+                }
+
+                fn scalar_lhs<const LANES: usize>() {
+                    test_helpers::test_binary_scalar_lhs_elementwise(
+                        &<$scalar as core::ops::$trait<Simd<$scalar, LANES>>>::$fn,
+                        &$scalar_fn,
+                        &|_, _| true,
+                    );
+                }
+
+                fn assign<const LANES: usize>() {
+                    test_helpers::test_binary_elementwise(
+                        &|mut a, b| { <Simd<$scalar, LANES> as core::ops::$trait_assign>::$fn_assign(&mut a, b); a },
+                        &$scalar_fn,
+                        &|_, _| true,
+                    );
+                }
+
+                fn assign_scalar_rhs<const LANES: usize>() {
+                    test_helpers::test_binary_scalar_rhs_elementwise(
+                        &|mut a, b| { <Simd<$scalar, LANES> as core::ops::$trait_assign<$scalar>>::$fn_assign(&mut a, b); a },
+                        &$scalar_fn,
+                        &|_, _| true,
+                    );
+                }
+            }
+        }
+    };
+    { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident } => {
+        impl_binary_op_test! { $scalar, $trait::$fn, $trait_assign::$fn_assign, <$scalar as core::ops::$trait>::$fn }
+    };
+}
+
+/// Implements a test on a binary operation using proptest.
+///
+/// Like `impl_binary_op_test`, but allows providing a function for rejecting particular inputs
+/// (like the `proptest_assume` macro).
+///
+/// Compares the vector operation to the equivalent scalar operation.
+#[macro_export]
+macro_rules! impl_binary_checked_op_test {
+    { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $scalar_fn:expr, $check_fn:expr } => {
+        mod $fn {
+            use super::*;
+            use core_simd::Simd;
+
+            test_helpers::test_lanes! {
+                fn normal<const LANES: usize>() {
+                    test_helpers::test_binary_elementwise(
+                        &<Simd<$scalar, LANES> as core::ops::$trait>::$fn,
+                        &$scalar_fn,
+                        &|x, y| x.iter().zip(y.iter()).all(|(x, y)| $check_fn(*x, *y)),
+                    );
+                }
+
+                fn scalar_rhs<const LANES: usize>() {
+                    test_helpers::test_binary_scalar_rhs_elementwise(
+                        &<Simd<$scalar, LANES> as core::ops::$trait<$scalar>>::$fn,
+                        &$scalar_fn,
+                        &|x, y| x.iter().all(|x| $check_fn(*x, y)),
+                    );
+                }
+
+                fn scalar_lhs<const LANES: usize>() {
+                    test_helpers::test_binary_scalar_lhs_elementwise(
+                        &<$scalar as core::ops::$trait<Simd<$scalar, LANES>>>::$fn,
+                        &$scalar_fn,
+                        &|x, y| y.iter().all(|y| $check_fn(x, *y)),
+                    );
+                }
+
+                fn assign<const LANES: usize>() {
+                    test_helpers::test_binary_elementwise(
+                        &|mut a, b| { <Simd<$scalar, LANES> as core::ops::$trait_assign>::$fn_assign(&mut a, b); a },
+                        &$scalar_fn,
+                        &|x, y| x.iter().zip(y.iter()).all(|(x, y)| $check_fn(*x, *y)),
+                    )
+                }
+
+                fn assign_scalar_rhs<const LANES: usize>() {
+                    test_helpers::test_binary_scalar_rhs_elementwise(
+                        &|mut a, b| { <Simd<$scalar, LANES> as core::ops::$trait_assign<$scalar>>::$fn_assign(&mut a, b); a },
+                        &$scalar_fn,
+                        &|x, y| x.iter().all(|x| $check_fn(*x, y)),
+                    )
+                }
+            }
+        }
+    };
+    { $scalar:ty, $trait:ident :: $fn:ident, $trait_assign:ident :: $fn_assign:ident, $check_fn:expr } => {
+        impl_binary_checked_op_test! { $scalar, $trait::$fn, $trait_assign::$fn_assign, <$scalar as core::ops::$trait>::$fn, $check_fn }
+    };
+}
+
+#[macro_export]
+macro_rules! impl_common_integer_tests {
+    { $vector:ident, $scalar:ident } => {
+        test_helpers::test_lanes! {
+            fn horizontal_sum<const LANES: usize>() {
+                test_helpers::test_1(&|x| {
+                    test_helpers::prop_assert_biteq! (
+                        $vector::<LANES>::from_array(x).horizontal_sum(),
+                        x.iter().copied().fold(0 as $scalar, $scalar::wrapping_add),
+                    );
+                    Ok(())
+                });
+            }
+
+            fn horizontal_product<const LANES: usize>() {
+                test_helpers::test_1(&|x| {
+                    test_helpers::prop_assert_biteq! (
+                        $vector::<LANES>::from_array(x).horizontal_product(),
+                        x.iter().copied().fold(1 as $scalar, $scalar::wrapping_mul),
+                    );
+                    Ok(())
+                });
+            }
+
+            fn horizontal_and<const LANES: usize>() {
+                test_helpers::test_1(&|x| {
+                    test_helpers::prop_assert_biteq! (
+                        $vector::<LANES>::from_array(x).horizontal_and(),
+                        x.iter().copied().fold(-1i8 as $scalar, <$scalar as core::ops::BitAnd>::bitand),
+                    );
+                    Ok(())
+                });
+            }
+
+            fn horizontal_or<const LANES: usize>() {
+                test_helpers::test_1(&|x| {
+                    test_helpers::prop_assert_biteq! (
+                        $vector::<LANES>::from_array(x).horizontal_or(),
+                        x.iter().copied().fold(0 as $scalar, <$scalar as core::ops::BitOr>::bitor),
+                    );
+                    Ok(())
+                });
+            }
+
+            fn horizontal_xor<const LANES: usize>() {
+                test_helpers::test_1(&|x| {
+                    test_helpers::prop_assert_biteq! (
+                        $vector::<LANES>::from_array(x).horizontal_xor(),
+                        x.iter().copied().fold(0 as $scalar, <$scalar as core::ops::BitXor>::bitxor),
+                    );
+                    Ok(())
+                });
+            }
+
+            fn horizontal_max<const LANES: usize>() {
+                test_helpers::test_1(&|x| {
+                    test_helpers::prop_assert_biteq! (
+                        $vector::<LANES>::from_array(x).horizontal_max(),
+                        x.iter().copied().max().unwrap(),
+                    );
+                    Ok(())
+                });
+            }
+
+            fn horizontal_min<const LANES: usize>() {
+                test_helpers::test_1(&|x| {
+                    test_helpers::prop_assert_biteq! (
+                        $vector::<LANES>::from_array(x).horizontal_min(),
+                        x.iter().copied().min().unwrap(),
+                    );
+                    Ok(())
+                });
+            }
+        }
+    }
+}
+
+/// Implement tests for signed integers.
+#[macro_export]
+macro_rules! impl_signed_tests {
+    { $scalar:tt } => {
+        mod $scalar {
+            type Vector<const LANES: usize> = core_simd::Simd<Scalar, LANES>;
+            type Scalar = $scalar;
+
+            impl_common_integer_tests! { Vector, Scalar }
+
+            test_helpers::test_lanes! {
+                fn neg<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &<Vector::<LANES> as core::ops::Neg>::neg,
+                        &<Scalar as core::ops::Neg>::neg,
+                        &|x| !x.contains(&Scalar::MIN),
+                    );
+                }
+
+                fn is_positive<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_positive,
+                        &Scalar::is_positive,
+                        &|_| true,
+                    );
+                }
+
+                fn is_negative<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_negative,
+                        &Scalar::is_negative,
+                        &|_| true,
+                    );
+                }
+
+                fn signum<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::signum,
+                        &Scalar::signum,
+                        &|_| true,
+                    )
+                }
+
+            }
+
+            test_helpers::test_lanes_panic! {
+                fn div_min_overflow_panics<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(Scalar::MIN);
+                    let b = Vector::<LANES>::splat(-1);
+                    let _ = a / b;
+                }
+
+                fn div_by_all_zeros_panics<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(42);
+                    let b = Vector::<LANES>::splat(0);
+                    let _ = a / b;
+                }
+
+                fn div_by_one_zero_panics<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(42);
+                    let mut b = Vector::<LANES>::splat(21);
+                    b[0] = 0 as _;
+                    let _ = a / b;
+                }
+
+                fn rem_min_overflow_panic<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(Scalar::MIN);
+                    let b = Vector::<LANES>::splat(-1);
+                    let _ = a % b;
+                }
+
+                fn rem_zero_panic<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(42);
+                    let b = Vector::<LANES>::splat(0);
+                    let _ = a % b;
+                }
+            }
+
+            test_helpers::test_lanes! {
+                fn div_neg_one_no_panic<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(42);
+                    let b = Vector::<LANES>::splat(-1);
+                    let _ = a / b;
+                }
+
+                fn rem_neg_one_no_panic<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(42);
+                    let b = Vector::<LANES>::splat(-1);
+                    let _ = a % b;
+                }
+            }
+
+            impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add);
+            impl_binary_op_test!(Scalar, Sub::sub, SubAssign::sub_assign, Scalar::wrapping_sub);
+            impl_binary_op_test!(Scalar, Mul::mul, MulAssign::mul_assign, Scalar::wrapping_mul);
+
+            // Exclude Div and Rem panicking cases
+            impl_binary_checked_op_test!(Scalar, Div::div, DivAssign::div_assign, Scalar::wrapping_div, |x, y| y != 0 && !(x == Scalar::MIN && y == -1));
+            impl_binary_checked_op_test!(Scalar, Rem::rem, RemAssign::rem_assign, Scalar::wrapping_rem, |x, y| y != 0 && !(x == Scalar::MIN && y == -1));
+
+            impl_unary_op_test!(Scalar, Not::not);
+            impl_binary_op_test!(Scalar, BitAnd::bitand, BitAndAssign::bitand_assign);
+            impl_binary_op_test!(Scalar, BitOr::bitor, BitOrAssign::bitor_assign);
+            impl_binary_op_test!(Scalar, BitXor::bitxor, BitXorAssign::bitxor_assign);
+        }
+    }
+}
+
+/// Implement tests for unsigned integers.
+#[macro_export]
+macro_rules! impl_unsigned_tests {
+    { $scalar:tt } => {
+        mod $scalar {
+            type Vector<const LANES: usize> = core_simd::Simd<Scalar, LANES>;
+            type Scalar = $scalar;
+
+            impl_common_integer_tests! { Vector, Scalar }
+
+            test_helpers::test_lanes_panic! {
+                fn rem_zero_panic<const LANES: usize>() {
+                    let a = Vector::<LANES>::splat(42);
+                    let b = Vector::<LANES>::splat(0);
+                    let _ = a % b;
+                }
+            }
+
+            impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add);
+            impl_binary_op_test!(Scalar, Sub::sub, SubAssign::sub_assign, Scalar::wrapping_sub);
+            impl_binary_op_test!(Scalar, Mul::mul, MulAssign::mul_assign, Scalar::wrapping_mul);
+
+            // Exclude Div and Rem panicking cases
+            impl_binary_checked_op_test!(Scalar, Div::div, DivAssign::div_assign, Scalar::wrapping_div, |_, y| y != 0);
+            impl_binary_checked_op_test!(Scalar, Rem::rem, RemAssign::rem_assign, Scalar::wrapping_rem, |_, y| y != 0);
+
+            impl_unary_op_test!(Scalar, Not::not);
+            impl_binary_op_test!(Scalar, BitAnd::bitand, BitAndAssign::bitand_assign);
+            impl_binary_op_test!(Scalar, BitOr::bitor, BitOrAssign::bitor_assign);
+            impl_binary_op_test!(Scalar, BitXor::bitxor, BitXorAssign::bitxor_assign);
+        }
+    }
+}
+
+/// Implement tests for floating point numbers.
+#[macro_export]
+macro_rules! impl_float_tests {
+    { $scalar:tt, $int_scalar:tt } => {
+        mod $scalar {
+            type Vector<const LANES: usize> = core_simd::Simd<Scalar, LANES>;
+            type Scalar = $scalar;
+
+            impl_unary_op_test!(Scalar, Neg::neg);
+            impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign);
+            impl_binary_op_test!(Scalar, Sub::sub, SubAssign::sub_assign);
+            impl_binary_op_test!(Scalar, Mul::mul, MulAssign::mul_assign);
+            impl_binary_op_test!(Scalar, Div::div, DivAssign::div_assign);
+            impl_binary_op_test!(Scalar, Rem::rem, RemAssign::rem_assign);
+
+            test_helpers::test_lanes! {
+                fn is_sign_positive<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_sign_positive,
+                        &Scalar::is_sign_positive,
+                        &|_| true,
+                    );
+                }
+
+                fn is_sign_negative<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_sign_negative,
+                        &Scalar::is_sign_negative,
+                        &|_| true,
+                    );
+                }
+
+                fn is_finite<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_finite,
+                        &Scalar::is_finite,
+                        &|_| true,
+                    );
+                }
+
+                fn is_infinite<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_infinite,
+                        &Scalar::is_infinite,
+                        &|_| true,
+                    );
+                }
+
+                fn is_nan<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_nan,
+                        &Scalar::is_nan,
+                        &|_| true,
+                    );
+                }
+
+                fn is_normal<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_normal,
+                        &Scalar::is_normal,
+                        &|_| true,
+                    );
+                }
+
+                fn is_subnormal<const LANES: usize>() {
+                    test_helpers::test_unary_mask_elementwise(
+                        &Vector::<LANES>::is_subnormal,
+                        &Scalar::is_subnormal,
+                        &|_| true,
+                    );
+                }
+
+                fn abs<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::abs,
+                        &Scalar::abs,
+                        &|_| true,
+                    )
+                }
+
+                fn recip<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::recip,
+                        &Scalar::recip,
+                        &|_| true,
+                    )
+                }
+
+                fn to_degrees<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::to_degrees,
+                        &Scalar::to_degrees,
+                        &|_| true,
+                    )
+                }
+
+                fn to_radians<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::to_radians,
+                        &Scalar::to_radians,
+                        &|_| true,
+                    )
+                }
+
+                fn signum<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::signum,
+                        &Scalar::signum,
+                        &|_| true,
+                    )
+                }
+
+                fn copysign<const LANES: usize>() {
+                    test_helpers::test_binary_elementwise(
+                        &Vector::<LANES>::copysign,
+                        &Scalar::copysign,
+                        &|_, _| true,
+                    )
+                }
+
+                fn min<const LANES: usize>() {
+                    // Regular conditions (both values aren't zero)
+                    test_helpers::test_binary_elementwise(
+                        &Vector::<LANES>::min,
+                        &Scalar::min,
+                        // Reject the case where both values are zero with different signs
+                        &|a, b| {
+                            for (a, b) in a.iter().zip(b.iter()) {
+                                if *a == 0. && *b == 0. && a.signum() != b.signum() {
+                                    return false;
+                                }
+                            }
+                            true
+                        }
+                    );
+
+                    // Special case where both values are zero
+                    let p_zero = Vector::<LANES>::splat(0.);
+                    let n_zero = Vector::<LANES>::splat(-0.);
+                    assert!(p_zero.min(n_zero).to_array().iter().all(|x| *x == 0.));
+                    assert!(n_zero.min(p_zero).to_array().iter().all(|x| *x == 0.));
+                }
+
+                fn max<const LANES: usize>() {
+                    // Regular conditions (both values aren't zero)
+                    test_helpers::test_binary_elementwise(
+                        &Vector::<LANES>::max,
+                        &Scalar::max,
+                        // Reject the case where both values are zero with different signs
+                        &|a, b| {
+                            for (a, b) in a.iter().zip(b.iter()) {
+                                if *a == 0. && *b == 0. && a.signum() != b.signum() {
+                                    return false;
+                                }
+                            }
+                            true
+                        }
+                    );
+
+                    // Special case where both values are zero
+                    let p_zero = Vector::<LANES>::splat(0.);
+                    let n_zero = Vector::<LANES>::splat(-0.);
+                    assert!(p_zero.max(n_zero).to_array().iter().all(|x| *x == 0.));
+                    assert!(n_zero.max(p_zero).to_array().iter().all(|x| *x == 0.));
+                }
+
+                fn clamp<const LANES: usize>() {
+                    test_helpers::test_3(&|value: [Scalar; LANES], mut min: [Scalar; LANES], mut max: [Scalar; LANES]| {
+                        for (min, max) in min.iter_mut().zip(max.iter_mut()) {
+                            if max < min {
+                                core::mem::swap(min, max);
+                            }
+                            if min.is_nan() {
+                                *min = Scalar::NEG_INFINITY;
+                            }
+                            if max.is_nan() {
+                                *max = Scalar::INFINITY;
+                            }
+                        }
+
+                        let mut result_scalar = [Scalar::default(); LANES];
+                        for i in 0..LANES {
+                            result_scalar[i] = value[i].clamp(min[i], max[i]);
+                        }
+                        let result_vector = Vector::from_array(value).clamp(min.into(), max.into()).to_array();
+                        test_helpers::prop_assert_biteq!(result_scalar, result_vector);
+                        Ok(())
+                    })
+                }
+
+                fn horizontal_sum<const LANES: usize>() {
+                    test_helpers::test_1(&|x| {
+                        test_helpers::prop_assert_biteq! (
+                            Vector::<LANES>::from_array(x).horizontal_sum(),
+                            x.iter().sum(),
+                        );
+                        Ok(())
+                    });
+                }
+
+                fn horizontal_product<const LANES: usize>() {
+                    test_helpers::test_1(&|x| {
+                        test_helpers::prop_assert_biteq! (
+                            Vector::<LANES>::from_array(x).horizontal_product(),
+                            x.iter().product(),
+                        );
+                        Ok(())
+                    });
+                }
+
+                fn horizontal_max<const LANES: usize>() {
+                    test_helpers::test_1(&|x| {
+                        let vmax = Vector::<LANES>::from_array(x).horizontal_max();
+                        let smax = x.iter().copied().fold(Scalar::NAN, Scalar::max);
+                        // 0 and -0 are treated the same
+                        if !(x.contains(&0.) && x.contains(&-0.) && vmax.abs() == 0. && smax.abs() == 0.) {
+                            test_helpers::prop_assert_biteq!(vmax, smax);
+                        }
+                        Ok(())
+                    });
+                }
+
+                fn horizontal_min<const LANES: usize>() {
+                    test_helpers::test_1(&|x| {
+                        let vmax = Vector::<LANES>::from_array(x).horizontal_min();
+                        let smax = x.iter().copied().fold(Scalar::NAN, Scalar::min);
+                        // 0 and -0 are treated the same
+                        if !(x.contains(&0.) && x.contains(&-0.) && vmax.abs() == 0. && smax.abs() == 0.) {
+                            test_helpers::prop_assert_biteq!(vmax, smax);
+                        }
+                        Ok(())
+                    });
+                }
+            }
+
+            #[cfg(feature = "std")]
+            mod std {
+                use super::*;
+                test_helpers::test_lanes! {
+                    fn sqrt<const LANES: usize>() {
+                        test_helpers::test_unary_elementwise(
+                            &Vector::<LANES>::sqrt,
+                            &Scalar::sqrt,
+                            &|_| true,
+                        )
+                    }
+
+                    fn mul_add<const LANES: usize>() {
+                        test_helpers::test_ternary_elementwise(
+                            &Vector::<LANES>::mul_add,
+                            &Scalar::mul_add,
+                            &|_, _, _| true,
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/library/portable-simd/crates/core_simd/tests/round.rs b/library/portable-simd/crates/core_simd/tests/round.rs
new file mode 100644 (file)
index 0000000..11d617a
--- /dev/null
@@ -0,0 +1,92 @@
+#![feature(portable_simd)]
+
+macro_rules! float_rounding_test {
+    { $scalar:tt, $int_scalar:tt } => {
+        mod $scalar {
+            type Vector<const LANES: usize> = core_simd::Simd<$scalar, LANES>;
+            type Scalar = $scalar;
+            type IntScalar = $int_scalar;
+
+            #[cfg(feature = "std")]
+            test_helpers::test_lanes! {
+                fn ceil<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::ceil,
+                        &Scalar::ceil,
+                        &|_| true,
+                    )
+                }
+
+                fn floor<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::floor,
+                        &Scalar::floor,
+                        &|_| true,
+                    )
+                }
+
+                fn round<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::round,
+                        &Scalar::round,
+                        &|_| true,
+                    )
+                }
+
+                fn trunc<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::trunc,
+                        &Scalar::trunc,
+                        &|_| true,
+                    )
+                }
+
+                fn fract<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::fract,
+                        &Scalar::fract,
+                        &|_| true,
+                    )
+                }
+            }
+
+            test_helpers::test_lanes! {
+                fn from_int<const LANES: usize>() {
+                    test_helpers::test_unary_elementwise(
+                        &Vector::<LANES>::round_from_int,
+                        &|x| x as Scalar,
+                        &|_| true,
+                    )
+                }
+
+                fn to_int_unchecked<const LANES: usize>() {
+                    // The maximum integer that can be represented by the equivalently sized float has
+                    // all of the mantissa digits set to 1, pushed up to the MSB.
+                    const ALL_MANTISSA_BITS: IntScalar = ((1 << <Scalar>::MANTISSA_DIGITS) - 1);
+                    const MAX_REPRESENTABLE_VALUE: Scalar =
+                        (ALL_MANTISSA_BITS << (core::mem::size_of::<Scalar>() * 8 - <Scalar>::MANTISSA_DIGITS as usize - 1)) as Scalar;
+
+                    let mut runner = proptest::test_runner::TestRunner::default();
+                    runner.run(
+                        &test_helpers::array::UniformArrayStrategy::new(-MAX_REPRESENTABLE_VALUE..MAX_REPRESENTABLE_VALUE),
+                        |x| {
+                            let result_1 = unsafe { Vector::from_array(x).to_int_unchecked().to_array() };
+                            let result_2 = {
+                                let mut result = [0; LANES];
+                                for (i, o) in x.iter().zip(result.iter_mut()) {
+                                    *o = unsafe { i.to_int_unchecked() };
+                                }
+                                result
+                            };
+                            test_helpers::prop_assert_biteq!(result_1, result_2);
+                            Ok(())
+                        },
+                    ).unwrap();
+                }
+            }
+        }
+    }
+}
+
+float_rounding_test! { f32, i32 }
+float_rounding_test! { f64, i64 }
diff --git a/library/portable-simd/crates/core_simd/tests/swizzle.rs b/library/portable-simd/crates/core_simd/tests/swizzle.rs
new file mode 100644 (file)
index 0000000..51c6361
--- /dev/null
@@ -0,0 +1,62 @@
+#![feature(portable_simd)]
+use core_simd::{Simd, Swizzle};
+
+#[cfg(target_arch = "wasm32")]
+use wasm_bindgen_test::*;
+
+#[cfg(target_arch = "wasm32")]
+wasm_bindgen_test_configure!(run_in_browser);
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn swizzle() {
+    struct Index;
+    impl Swizzle<4, 4> for Index {
+        const INDEX: [usize; 4] = [2, 1, 3, 0];
+    }
+    impl Swizzle<4, 2> for Index {
+        const INDEX: [usize; 2] = [1, 1];
+    }
+
+    let vector = Simd::from_array([2, 4, 1, 9]);
+    assert_eq!(Index::swizzle(vector).to_array(), [1, 4, 9, 2]);
+    assert_eq!(Index::swizzle(vector).to_array(), [4, 4]);
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn reverse() {
+    let a = Simd::from_array([1, 2, 3, 4]);
+    assert_eq!(a.reverse().to_array(), [4, 3, 2, 1]);
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn rotate() {
+    let a = Simd::from_array([1, 2, 3, 4]);
+    assert_eq!(a.rotate_lanes_left::<0>().to_array(), [1, 2, 3, 4]);
+    assert_eq!(a.rotate_lanes_left::<1>().to_array(), [2, 3, 4, 1]);
+    assert_eq!(a.rotate_lanes_left::<2>().to_array(), [3, 4, 1, 2]);
+    assert_eq!(a.rotate_lanes_left::<3>().to_array(), [4, 1, 2, 3]);
+    assert_eq!(a.rotate_lanes_left::<4>().to_array(), [1, 2, 3, 4]);
+    assert_eq!(a.rotate_lanes_left::<5>().to_array(), [2, 3, 4, 1]);
+    assert_eq!(a.rotate_lanes_right::<0>().to_array(), [1, 2, 3, 4]);
+    assert_eq!(a.rotate_lanes_right::<1>().to_array(), [4, 1, 2, 3]);
+    assert_eq!(a.rotate_lanes_right::<2>().to_array(), [3, 4, 1, 2]);
+    assert_eq!(a.rotate_lanes_right::<3>().to_array(), [2, 3, 4, 1]);
+    assert_eq!(a.rotate_lanes_right::<4>().to_array(), [1, 2, 3, 4]);
+    assert_eq!(a.rotate_lanes_right::<5>().to_array(), [4, 1, 2, 3]);
+}
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn interleave() {
+    let a = Simd::from_array([0, 1, 2, 3, 4, 5, 6, 7]);
+    let b = Simd::from_array([8, 9, 10, 11, 12, 13, 14, 15]);
+    let (lo, hi) = a.interleave(b);
+    assert_eq!(lo.to_array(), [0, 8, 1, 9, 2, 10, 3, 11]);
+    assert_eq!(hi.to_array(), [4, 12, 5, 13, 6, 14, 7, 15]);
+    let (even, odd) = lo.deinterleave(hi);
+    assert_eq!(even, a);
+    assert_eq!(odd, b);
+}
diff --git a/library/portable-simd/crates/core_simd/tests/to_bytes.rs b/library/portable-simd/crates/core_simd/tests/to_bytes.rs
new file mode 100644 (file)
index 0000000..debb433
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(portable_simd, generic_const_exprs, adt_const_params)]
+#![allow(incomplete_features)]
+#![cfg(feature = "generic_const_exprs")]
+
+use core_simd::Simd;
+
+#[test]
+fn byte_convert() {
+    let int = Simd::<u32, 2>::from_array([0xdeadbeef, 0x8badf00d]);
+    let bytes = int.to_ne_bytes();
+    assert_eq!(int[0].to_ne_bytes(), bytes[..4]);
+    assert_eq!(int[1].to_ne_bytes(), bytes[4..]);
+    assert_eq!(Simd::<u32, 2>::from_ne_bytes(bytes), int);
+}
diff --git a/library/portable-simd/crates/core_simd/tests/u16_ops.rs b/library/portable-simd/crates/core_simd/tests/u16_ops.rs
new file mode 100644 (file)
index 0000000..9ae3bd6
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_unsigned_tests! { u16 }
diff --git a/library/portable-simd/crates/core_simd/tests/u32_ops.rs b/library/portable-simd/crates/core_simd/tests/u32_ops.rs
new file mode 100644 (file)
index 0000000..de34b73
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_unsigned_tests! { u32 }
diff --git a/library/portable-simd/crates/core_simd/tests/u64_ops.rs b/library/portable-simd/crates/core_simd/tests/u64_ops.rs
new file mode 100644 (file)
index 0000000..8ee5a31
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_unsigned_tests! { u64 }
diff --git a/library/portable-simd/crates/core_simd/tests/u8_ops.rs b/library/portable-simd/crates/core_simd/tests/u8_ops.rs
new file mode 100644 (file)
index 0000000..6d72111
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_unsigned_tests! { u8 }
diff --git a/library/portable-simd/crates/core_simd/tests/usize_ops.rs b/library/portable-simd/crates/core_simd/tests/usize_ops.rs
new file mode 100644 (file)
index 0000000..9c7b168
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(portable_simd)]
+
+#[macro_use]
+mod ops_macros;
+impl_unsigned_tests! { usize }
diff --git a/library/portable-simd/crates/core_simd/webdriver.json b/library/portable-simd/crates/core_simd/webdriver.json
new file mode 100644 (file)
index 0000000..f1d5734
--- /dev/null
@@ -0,0 +1,7 @@
+{
+    "goog:chromeOptions": {
+        "args": [
+            "--enable-features=WebAssemblySimd"
+        ]
+    }
+}
diff --git a/library/portable-simd/crates/test_helpers/Cargo.toml b/library/portable-simd/crates/test_helpers/Cargo.toml
new file mode 100644 (file)
index 0000000..a04b096
--- /dev/null
@@ -0,0 +1,10 @@
+[package]
+name = "test_helpers"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[dependencies.proptest]
+version = "0.10"
+default-features = false
+features = ["alloc"]
diff --git a/library/portable-simd/crates/test_helpers/src/array.rs b/library/portable-simd/crates/test_helpers/src/array.rs
new file mode 100644 (file)
index 0000000..5ffc922
--- /dev/null
@@ -0,0 +1,97 @@
+//! Generic-length array strategy.
+
+// Adapted from proptest's array code
+// Copyright 2017 Jason Lingle
+
+use core::{marker::PhantomData, mem::MaybeUninit};
+use proptest::{
+    strategy::{NewTree, Strategy, ValueTree},
+    test_runner::TestRunner,
+};
+
+#[must_use = "strategies do nothing unless used"]
+#[derive(Clone, Copy, Debug)]
+pub struct UniformArrayStrategy<S, T> {
+    strategy: S,
+    _marker: PhantomData<T>,
+}
+
+impl<S, T> UniformArrayStrategy<S, T> {
+    pub const fn new(strategy: S) -> Self {
+        Self {
+            strategy,
+            _marker: PhantomData,
+        }
+    }
+}
+
+pub struct ArrayValueTree<T> {
+    tree: T,
+    shrinker: usize,
+    last_shrinker: Option<usize>,
+}
+
+impl<T, S, const LANES: usize> Strategy for UniformArrayStrategy<S, [T; LANES]>
+where
+    T: core::fmt::Debug,
+    S: Strategy<Value = T>,
+{
+    type Tree = ArrayValueTree<[S::Tree; LANES]>;
+    type Value = [T; LANES];
+
+    fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
+        let tree: [S::Tree; LANES] = unsafe {
+            let mut tree: [MaybeUninit<S::Tree>; LANES] = MaybeUninit::uninit().assume_init();
+            for t in tree.iter_mut() {
+                *t = MaybeUninit::new(self.strategy.new_tree(runner)?)
+            }
+            core::mem::transmute_copy(&tree)
+        };
+        Ok(ArrayValueTree {
+            tree,
+            shrinker: 0,
+            last_shrinker: None,
+        })
+    }
+}
+
+impl<T: ValueTree, const LANES: usize> ValueTree for ArrayValueTree<[T; LANES]> {
+    type Value = [T::Value; LANES];
+
+    fn current(&self) -> Self::Value {
+        unsafe {
+            let mut value: [MaybeUninit<T::Value>; LANES] = MaybeUninit::uninit().assume_init();
+            for (tree_elem, value_elem) in self.tree.iter().zip(value.iter_mut()) {
+                *value_elem = MaybeUninit::new(tree_elem.current());
+            }
+            core::mem::transmute_copy(&value)
+        }
+    }
+
+    fn simplify(&mut self) -> bool {
+        while self.shrinker < LANES {
+            if self.tree[self.shrinker].simplify() {
+                self.last_shrinker = Some(self.shrinker);
+                return true;
+            } else {
+                self.shrinker += 1;
+            }
+        }
+
+        false
+    }
+
+    fn complicate(&mut self) -> bool {
+        if let Some(shrinker) = self.last_shrinker {
+            self.shrinker = shrinker;
+            if self.tree[shrinker].complicate() {
+                true
+            } else {
+                self.last_shrinker = None;
+                false
+            }
+        } else {
+            false
+        }
+    }
+}
diff --git a/library/portable-simd/crates/test_helpers/src/biteq.rs b/library/portable-simd/crates/test_helpers/src/biteq.rs
new file mode 100644 (file)
index 0000000..00350e2
--- /dev/null
@@ -0,0 +1,106 @@
+//! Compare numeric types by exact bit value.
+
+pub trait BitEq {
+    fn biteq(&self, other: &Self) -> bool;
+    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result;
+}
+
+impl BitEq for bool {
+    fn biteq(&self, other: &Self) -> bool {
+        self == other
+    }
+
+    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+macro_rules! impl_integer_biteq {
+    { $($type:ty),* } => {
+        $(
+        impl BitEq for $type {
+            fn biteq(&self, other: &Self) -> bool {
+                self == other
+            }
+
+            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+                write!(f, "{:?} ({:x})", self, self)
+            }
+        }
+        )*
+    };
+}
+
+impl_integer_biteq! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize }
+
+macro_rules! impl_float_biteq {
+    { $($type:ty),* } => {
+        $(
+        impl BitEq for $type {
+            fn biteq(&self, other: &Self) -> bool {
+                if self.is_nan() && other.is_nan() {
+                    true // exact nan bits don't matter
+                } else {
+                    self.to_bits() == other.to_bits()
+                }
+            }
+
+            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+                write!(f, "{:?} ({:x})", self, self.to_bits())
+            }
+        }
+        )*
+    };
+}
+
+impl_float_biteq! { f32, f64 }
+
+impl<T: BitEq, const N: usize> BitEq for [T; N] {
+    fn biteq(&self, other: &Self) -> bool {
+        self.iter()
+            .zip(other.iter())
+            .fold(true, |value, (left, right)| value && left.biteq(right))
+    }
+
+    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+        #[repr(transparent)]
+        struct Wrapper<'a, T: BitEq>(&'a T);
+
+        impl<T: BitEq> core::fmt::Debug for Wrapper<'_, T> {
+            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+                self.0.fmt(f)
+            }
+        }
+
+        f.debug_list()
+            .entries(self.iter().map(|x| Wrapper(x)))
+            .finish()
+    }
+}
+
+#[doc(hidden)]
+pub struct BitEqWrapper<'a, T>(pub &'a T);
+
+impl<T: BitEq> PartialEq for BitEqWrapper<'_, T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.0.biteq(other.0)
+    }
+}
+
+impl<T: BitEq> core::fmt::Debug for BitEqWrapper<'_, T> {
+    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[macro_export]
+macro_rules! prop_assert_biteq {
+    { $a:expr, $b:expr $(,)? } => {
+        {
+            use $crate::biteq::BitEqWrapper;
+            let a = $a;
+            let b = $b;
+            proptest::prop_assert_eq!(BitEqWrapper(&a), BitEqWrapper(&b));
+        }
+    }
+}
diff --git a/library/portable-simd/crates/test_helpers/src/lib.rs b/library/portable-simd/crates/test_helpers/src/lib.rs
new file mode 100644 (file)
index 0000000..5c64788
--- /dev/null
@@ -0,0 +1,437 @@
+pub mod array;
+
+#[cfg(target_arch = "wasm32")]
+pub mod wasm;
+
+#[macro_use]
+pub mod biteq;
+
+/// Specifies the default strategy for testing a type.
+///
+/// This strategy should be what "makes sense" to test.
+pub trait DefaultStrategy {
+    type Strategy: proptest::strategy::Strategy<Value = Self>;
+    fn default_strategy() -> Self::Strategy;
+}
+
+macro_rules! impl_num {
+    { $type:tt } => {
+        impl DefaultStrategy for $type {
+            type Strategy = proptest::num::$type::Any;
+            fn default_strategy() -> Self::Strategy {
+                proptest::num::$type::ANY
+            }
+        }
+    }
+}
+
+impl_num! { i8 }
+impl_num! { i16 }
+impl_num! { i32 }
+impl_num! { i64 }
+impl_num! { isize }
+impl_num! { u8 }
+impl_num! { u16 }
+impl_num! { u32 }
+impl_num! { u64 }
+impl_num! { usize }
+impl_num! { f32 }
+impl_num! { f64 }
+
+#[cfg(not(target_arch = "wasm32"))]
+impl DefaultStrategy for u128 {
+    type Strategy = proptest::num::u128::Any;
+    fn default_strategy() -> Self::Strategy {
+        proptest::num::u128::ANY
+    }
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+impl DefaultStrategy for i128 {
+    type Strategy = proptest::num::i128::Any;
+    fn default_strategy() -> Self::Strategy {
+        proptest::num::i128::ANY
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+impl DefaultStrategy for u128 {
+    type Strategy = crate::wasm::u128::Any;
+    fn default_strategy() -> Self::Strategy {
+        crate::wasm::u128::ANY
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+impl DefaultStrategy for i128 {
+    type Strategy = crate::wasm::i128::Any;
+    fn default_strategy() -> Self::Strategy {
+        crate::wasm::i128::ANY
+    }
+}
+
+impl<T: core::fmt::Debug + DefaultStrategy, const LANES: usize> DefaultStrategy for [T; LANES] {
+    type Strategy = crate::array::UniformArrayStrategy<T::Strategy, Self>;
+    fn default_strategy() -> Self::Strategy {
+        Self::Strategy::new(T::default_strategy())
+    }
+}
+
+/// Test a function that takes a single value.
+pub fn test_1<A: core::fmt::Debug + DefaultStrategy>(
+    f: &dyn Fn(A) -> proptest::test_runner::TestCaseResult,
+) {
+    let mut runner = proptest::test_runner::TestRunner::default();
+    runner.run(&A::default_strategy(), f).unwrap();
+}
+
+/// Test a function that takes two values.
+pub fn test_2<A: core::fmt::Debug + DefaultStrategy, B: core::fmt::Debug + DefaultStrategy>(
+    f: &dyn Fn(A, B) -> proptest::test_runner::TestCaseResult,
+) {
+    let mut runner = proptest::test_runner::TestRunner::default();
+    runner
+        .run(&(A::default_strategy(), B::default_strategy()), |(a, b)| {
+            f(a, b)
+        })
+        .unwrap();
+}
+
+/// Test a function that takes two values.
+pub fn test_3<
+    A: core::fmt::Debug + DefaultStrategy,
+    B: core::fmt::Debug + DefaultStrategy,
+    C: core::fmt::Debug + DefaultStrategy,
+>(
+    f: &dyn Fn(A, B, C) -> proptest::test_runner::TestCaseResult,
+) {
+    let mut runner = proptest::test_runner::TestRunner::default();
+    runner
+        .run(
+            &(
+                A::default_strategy(),
+                B::default_strategy(),
+                C::default_strategy(),
+            ),
+            |(a, b, c)| f(a, b, c),
+        )
+        .unwrap();
+}
+
+/// Test a unary vector function against a unary scalar function, applied elementwise.
+#[inline(never)]
+pub fn test_unary_elementwise<Scalar, ScalarResult, Vector, VectorResult, const LANES: usize>(
+    fv: &dyn Fn(Vector) -> VectorResult,
+    fs: &dyn Fn(Scalar) -> ScalarResult,
+    check: &dyn Fn([Scalar; LANES]) -> bool,
+) where
+    Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
+    Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy,
+    VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
+{
+    test_1(&|x: [Scalar; LANES]| {
+        proptest::prop_assume!(check(x));
+        let result_1: [ScalarResult; LANES] = fv(x.into()).into();
+        let result_2: [ScalarResult; LANES] = {
+            let mut result = [ScalarResult::default(); LANES];
+            for (i, o) in x.iter().zip(result.iter_mut()) {
+                *o = fs(*i);
+            }
+            result
+        };
+        crate::prop_assert_biteq!(result_1, result_2);
+        Ok(())
+    });
+}
+
+/// Test a unary vector function against a unary scalar function, applied elementwise.
+#[inline(never)]
+pub fn test_unary_mask_elementwise<Scalar, Vector, Mask, const LANES: usize>(
+    fv: &dyn Fn(Vector) -> Mask,
+    fs: &dyn Fn(Scalar) -> bool,
+    check: &dyn Fn([Scalar; LANES]) -> bool,
+) where
+    Scalar: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy,
+    Mask: Into<[bool; LANES]> + From<[bool; LANES]> + Copy,
+{
+    test_1(&|x: [Scalar; LANES]| {
+        proptest::prop_assume!(check(x));
+        let result_1: [bool; LANES] = fv(x.into()).into();
+        let result_2: [bool; LANES] = {
+            let mut result = [false; LANES];
+            for (i, o) in x.iter().zip(result.iter_mut()) {
+                *o = fs(*i);
+            }
+            result
+        };
+        crate::prop_assert_biteq!(result_1, result_2);
+        Ok(())
+    });
+}
+
+/// Test a binary vector function against a binary scalar function, applied elementwise.
+#[inline(never)]
+pub fn test_binary_elementwise<
+    Scalar1,
+    Scalar2,
+    ScalarResult,
+    Vector1,
+    Vector2,
+    VectorResult,
+    const LANES: usize,
+>(
+    fv: &dyn Fn(Vector1, Vector2) -> VectorResult,
+    fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult,
+    check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool,
+) where
+    Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
+    Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy,
+    Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy,
+    VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
+{
+    test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| {
+        proptest::prop_assume!(check(x, y));
+        let result_1: [ScalarResult; LANES] = fv(x.into(), y.into()).into();
+        let result_2: [ScalarResult; LANES] = {
+            let mut result = [ScalarResult::default(); LANES];
+            for ((i1, i2), o) in x.iter().zip(y.iter()).zip(result.iter_mut()) {
+                *o = fs(*i1, *i2);
+            }
+            result
+        };
+        crate::prop_assert_biteq!(result_1, result_2);
+        Ok(())
+    });
+}
+
+/// Test a binary vector-scalar function against a binary scalar function, applied elementwise.
+#[inline(never)]
+pub fn test_binary_scalar_rhs_elementwise<
+    Scalar1,
+    Scalar2,
+    ScalarResult,
+    Vector,
+    VectorResult,
+    const LANES: usize,
+>(
+    fv: &dyn Fn(Vector, Scalar2) -> VectorResult,
+    fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult,
+    check: &dyn Fn([Scalar1; LANES], Scalar2) -> bool,
+) where
+    Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
+    Vector: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy,
+    VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
+{
+    test_2(&|x: [Scalar1; LANES], y: Scalar2| {
+        proptest::prop_assume!(check(x, y));
+        let result_1: [ScalarResult; LANES] = fv(x.into(), y).into();
+        let result_2: [ScalarResult; LANES] = {
+            let mut result = [ScalarResult::default(); LANES];
+            for (i, o) in x.iter().zip(result.iter_mut()) {
+                *o = fs(*i, y);
+            }
+            result
+        };
+        crate::prop_assert_biteq!(result_1, result_2);
+        Ok(())
+    });
+}
+
+/// Test a binary vector-scalar function against a binary scalar function, applied elementwise.
+#[inline(never)]
+pub fn test_binary_scalar_lhs_elementwise<
+    Scalar1,
+    Scalar2,
+    ScalarResult,
+    Vector,
+    VectorResult,
+    const LANES: usize,
+>(
+    fv: &dyn Fn(Scalar1, Vector) -> VectorResult,
+    fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult,
+    check: &dyn Fn(Scalar1, [Scalar2; LANES]) -> bool,
+) where
+    Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
+    Vector: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy,
+    VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
+{
+    test_2(&|x: Scalar1, y: [Scalar2; LANES]| {
+        proptest::prop_assume!(check(x, y));
+        let result_1: [ScalarResult; LANES] = fv(x, y.into()).into();
+        let result_2: [ScalarResult; LANES] = {
+            let mut result = [ScalarResult::default(); LANES];
+            for (i, o) in y.iter().zip(result.iter_mut()) {
+                *o = fs(x, *i);
+            }
+            result
+        };
+        crate::prop_assert_biteq!(result_1, result_2);
+        Ok(())
+    });
+}
+
+/// Test a ternary vector function against a ternary scalar function, applied elementwise.
+#[inline(never)]
+pub fn test_ternary_elementwise<
+    Scalar1,
+    Scalar2,
+    Scalar3,
+    ScalarResult,
+    Vector1,
+    Vector2,
+    Vector3,
+    VectorResult,
+    const LANES: usize,
+>(
+    fv: &dyn Fn(Vector1, Vector2, Vector3) -> VectorResult,
+    fs: &dyn Fn(Scalar1, Scalar2, Scalar3) -> ScalarResult,
+    check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES], [Scalar3; LANES]) -> bool,
+) where
+    Scalar1: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    Scalar2: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    Scalar3: Copy + Default + core::fmt::Debug + DefaultStrategy,
+    ScalarResult: Copy + Default + biteq::BitEq + core::fmt::Debug + DefaultStrategy,
+    Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy,
+    Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy,
+    Vector3: Into<[Scalar3; LANES]> + From<[Scalar3; LANES]> + Copy,
+    VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy,
+{
+    test_3(
+        &|x: [Scalar1; LANES], y: [Scalar2; LANES], z: [Scalar3; LANES]| {
+            proptest::prop_assume!(check(x, y, z));
+            let result_1: [ScalarResult; LANES] = fv(x.into(), y.into(), z.into()).into();
+            let result_2: [ScalarResult; LANES] = {
+                let mut result = [ScalarResult::default(); LANES];
+                for ((i1, (i2, i3)), o) in
+                    x.iter().zip(y.iter().zip(z.iter())).zip(result.iter_mut())
+                {
+                    *o = fs(*i1, *i2, *i3);
+                }
+                result
+            };
+            crate::prop_assert_biteq!(result_1, result_2);
+            Ok(())
+        },
+    );
+}
+
+/// Expand a const-generic test into separate tests for each possible lane count.
+#[macro_export]
+macro_rules! test_lanes {
+    {
+        $(fn $test:ident<const $lanes:ident: usize>() $body:tt)*
+    } => {
+        $(
+            mod $test {
+                use super::*;
+
+                fn implementation<const $lanes: usize>()
+                where
+                    core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount,
+                $body
+
+                #[cfg(target_arch = "wasm32")]
+                wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
+
+                #[test]
+                #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+                fn lanes_1() {
+                    implementation::<1>();
+                }
+
+                #[test]
+                #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+                fn lanes_2() {
+                    implementation::<2>();
+                }
+
+                #[test]
+                #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+                fn lanes_4() {
+                    implementation::<4>();
+                }
+
+                #[test]
+                #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+                fn lanes_8() {
+                    implementation::<8>();
+                }
+
+                #[test]
+                #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+                fn lanes_16() {
+                    implementation::<16>();
+                }
+
+                #[test]
+                #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
+                fn lanes_32() {
+                    implementation::<32>();
+                }
+            }
+        )*
+    }
+}
+
+/// Expand a const-generic `#[should_panic]` test into separate tests for each possible lane count.
+#[macro_export]
+macro_rules! test_lanes_panic {
+    {
+        $(fn $test:ident<const $lanes:ident: usize>() $body:tt)*
+    } => {
+        $(
+            mod $test {
+                use super::*;
+
+                fn implementation<const $lanes: usize>()
+                where
+                    core_simd::LaneCount<$lanes>: core_simd::SupportedLaneCount,
+                $body
+
+                #[test]
+                #[should_panic]
+                fn lanes_1() {
+                    implementation::<1>();
+                }
+
+                #[test]
+                #[should_panic]
+                fn lanes_2() {
+                    implementation::<2>();
+                }
+
+                #[test]
+                #[should_panic]
+                fn lanes_4() {
+                    implementation::<4>();
+                }
+
+                #[test]
+                #[should_panic]
+                fn lanes_8() {
+                    implementation::<8>();
+                }
+
+                #[test]
+                #[should_panic]
+                fn lanes_16() {
+                    implementation::<16>();
+                }
+
+                #[test]
+                #[should_panic]
+                fn lanes_32() {
+                    implementation::<32>();
+                }
+            }
+        )*
+    }
+}
diff --git a/library/portable-simd/crates/test_helpers/src/wasm.rs b/library/portable-simd/crates/test_helpers/src/wasm.rs
new file mode 100644 (file)
index 0000000..3f11d67
--- /dev/null
@@ -0,0 +1,51 @@
+//! Strategies for `u128` and `i128`, since proptest doesn't provide them for the wasm target.
+
+macro_rules! impl_num {
+    { $name:ident } => {
+        pub(crate) mod $name {
+            type InnerStrategy = crate::array::UniformArrayStrategy<proptest::num::u64::Any, [u64; 2]>;
+            use proptest::strategy::{Strategy, ValueTree, NewTree};
+
+
+            #[must_use = "strategies do nothing unless used"]
+            #[derive(Clone, Copy, Debug)]
+            pub struct Any {
+                strategy: InnerStrategy,
+            }
+
+            pub struct BinarySearch {
+                inner: <InnerStrategy as Strategy>::Tree,
+            }
+
+            impl ValueTree for BinarySearch {
+                type Value = $name;
+
+                fn current(&self) -> $name {
+                    unsafe { core::mem::transmute(self.inner.current()) }
+                }
+
+                fn simplify(&mut self) -> bool {
+                    self.inner.simplify()
+                }
+
+                fn complicate(&mut self) -> bool {
+                    self.inner.complicate()
+                }
+            }
+
+            impl Strategy for Any {
+                type Tree = BinarySearch;
+                type Value = $name;
+
+                fn new_tree(&self, runner: &mut proptest::test_runner::TestRunner) -> NewTree<Self> {
+                    Ok(BinarySearch { inner: self.strategy.new_tree(runner)? })
+                }
+            }
+
+            pub const ANY: Any = Any { strategy: InnerStrategy::new(proptest::num::u64::ANY) };
+        }
+    }
+}
+
+impl_num! { u128 }
+impl_num! { i128 }
index bb05506defd0778c8f1f24e72d2a9d1617a64121..2df287f7d93007f6546677246651401be51c33a2 100644 (file)
@@ -62,6 +62,7 @@ macro_rules! with_api {
                 fn clone($self: &$S::TokenStream) -> $S::TokenStream;
                 fn new() -> $S::TokenStream;
                 fn is_empty($self: &$S::TokenStream) -> bool;
+                fn expand_expr($self: &$S::TokenStream) -> Result<$S::TokenStream, ()>;
                 fn from_str(src: &str) -> $S::TokenStream;
                 fn to_string($self: &$S::TokenStream) -> String;
                 fn from_token_tree(
index 9d673d69687191dfb4525339593a7e2979506e11..ef96d72a38b54728f46f66f297dbf812b3746b04 100644 (file)
@@ -88,12 +88,6 @@ impl !Sync for TokenStream {}
 #[derive(Debug)]
 pub struct LexError;
 
-impl LexError {
-    fn new() -> Self {
-        LexError
-    }
-}
-
 #[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")]
 impl fmt::Display for LexError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -109,6 +103,28 @@ impl !Send for LexError {}
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl !Sync for LexError {}
 
+/// Error returned from `TokenStream::expand_expr`.
+#[unstable(feature = "proc_macro_expand", issue = "90765")]
+#[non_exhaustive]
+#[derive(Debug)]
+pub struct ExpandError;
+
+#[unstable(feature = "proc_macro_expand", issue = "90765")]
+impl fmt::Display for ExpandError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("macro expansion failed")
+    }
+}
+
+#[unstable(feature = "proc_macro_expand", issue = "90765")]
+impl error::Error for ExpandError {}
+
+#[unstable(feature = "proc_macro_expand", issue = "90765")]
+impl !Send for ExpandError {}
+
+#[unstable(feature = "proc_macro_expand", issue = "90765")]
+impl !Sync for ExpandError {}
+
 impl TokenStream {
     /// Returns an empty `TokenStream` containing no token trees.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
@@ -121,6 +137,24 @@ pub fn new() -> TokenStream {
     pub fn is_empty(&self) -> bool {
         self.0.is_empty()
     }
+
+    /// Parses this `TokenStream` as an expression and attempts to expand any
+    /// macros within it. Returns the expanded `TokenStream`.
+    ///
+    /// Currently only expressions expanding to literals will succeed, although
+    /// this may be relaxed in the future.
+    ///
+    /// NOTE: In error conditions, `expand_expr` may leave macros unexpanded,
+    /// report an error, failing compilation, and/or return an `Err(..)`. The
+    /// specific behavior for any error condition, and what conditions are
+    /// considered errors, is unspecified and may change in the future.
+    #[unstable(feature = "proc_macro_expand", issue = "90765")]
+    pub fn expand_expr(&self) -> Result<TokenStream, ExpandError> {
+        match bridge::client::TokenStream::expand_expr(&self.0) {
+            Ok(stream) => Ok(TokenStream(stream)),
+            Err(_) => Err(ExpandError),
+        }
+    }
 }
 
 /// Attempts to break the string into tokens and parse those tokens into a token stream.
@@ -1211,7 +1245,7 @@ impl FromStr for Literal {
     fn from_str(src: &str) -> Result<Self, LexError> {
         match bridge::client::Literal::from_str(src) {
             Ok(literal) => Ok(Literal(literal)),
-            Err(()) => Err(LexError::new()),
+            Err(()) => Err(LexError),
         }
     }
 }
index a19c3431989c0c262f7aa0115285650f1e87fadf..8b004525b469796203b3e6b6fb8a5e39eb7eaf89 100644 (file)
 //! not. Normally, this would require a `find` followed by an `insert`,
 //! effectively duplicating the search effort on each insertion.
 //!
-//! When a user calls `map.entry(&key)`, the map will search for the key and
+//! When a user calls `map.entry(key)`, the map will search for the key and
 //! then yield a variant of the `Entry` enum.
 //!
 //! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case
index 2e93807037464af71fddb3fe7c9004b5b2fcca23..a8365071d61eb5085ae3d497d0f7a5dc13d8e37c 100644 (file)
@@ -182,7 +182,7 @@ mod break_keyword {}
 /// T` and `*mut T`. More about `const` as used in raw pointers can be read at the Rust docs for the [pointer primitive].
 ///
 /// [pointer primitive]: pointer
-/// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
+/// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#constants
 /// [Reference]: ../reference/items/constant-items.html
 /// [const-eval]: ../reference/const_eval.html
 mod const_keyword {}
index eb8325504792e26f792050f028a7ae95a24e042b..f2490a77ce0f8aa72a86d9e3c22cb70d413fdaf6 100644 (file)
 #![feature(panic_internals)]
 #![feature(panic_unwind)]
 #![feature(pin_static_ref)]
+#![cfg_attr(not(bootstrap), feature(portable_simd))]
 #![feature(prelude_import)]
 #![feature(ptr_internals)]
 #![feature(rustc_attrs)]
 pub use core::ptr;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::result;
+#[unstable(feature = "portable_simd", issue = "86656")]
+#[cfg(not(bootstrap))]
+pub use core::simd;
 #[unstable(feature = "async_stream", issue = "79024")]
 pub use core::stream;
 #[stable(feature = "i128", since = "1.26.0")]
index 140647128a937d934b31d0c831c91f4593fce512..da95fe21ac9af8706e3d371d8b63382c1268efa7 100644 (file)
@@ -878,12 +878,7 @@ pub const fn is_broadcast(&self) -> bool {
     #[must_use]
     #[inline]
     pub const fn is_documentation(&self) -> bool {
-        match self.octets() {
-            [192, 0, 2, _] => true,
-            [198, 51, 100, _] => true,
-            [203, 0, 113, _] => true,
-            _ => false,
-        }
+        matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
     }
 
     /// Converts this address to an [IPv4-compatible] [`IPv6` address].
index 887f605993918da58f6c156882f96c27be843744..f450e41bfea1e539a0c7d0a2e476164b68dba909 100644 (file)
@@ -159,7 +159,7 @@ pub(super) fn from_parts(
     #[must_use]
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn is_unnamed(&self) -> bool {
-        if let AddressKind::Unnamed = self.address() { true } else { false }
+        matches!(self.address(), AddressKind::Unnamed)
     }
 
     /// Returns the contents of this address if it is a `pathname` address.
index 286a7c3b386f9d79e4d23c7db159242b91cdaa74..855f900430c4a4d05636ab6e6a0cf4ef6e0c6ec2 100644 (file)
@@ -39,7 +39,7 @@ fn gid(
 
     /// Sets the supplementary group IDs for the calling process. Translates to
     /// a `setgroups` call in the child process.
-    #[unstable(feature = "setgroups", issue = "38527", reason = "")]
+    #[unstable(feature = "setgroups", issue = "90747")]
     fn groups(
         &mut self,
         #[cfg(not(target_os = "vxworks"))] groups: &[u32],
@@ -207,7 +207,7 @@ fn arg0<S>(&mut self, arg: S) -> &mut process::Command
 /// [`ExitStatusError`](process::ExitStatusError).
 ///
 /// On Unix, `ExitStatus` **does not necessarily represent an exit status**, as
-/// passed to the `exit` system call or returned by
+/// passed to the `_exit` system call or returned by
 /// [`ExitStatus::code()`](crate::process::ExitStatus::code).  It represents **any wait status**
 /// as returned by one of the `wait` family of system
 /// calls.
index 72a17adb3b4707b3353a63c27073c98ad43b338c..1527f5b6b07e0d05afc2b78fe6b4784b59644889 100644 (file)
@@ -4,12 +4,10 @@
 
 use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
 use crate::convert::TryFrom;
-use crate::ffi::c_void;
 use crate::fmt;
 use crate::fs;
 use crate::marker::PhantomData;
 use crate::mem::forget;
-use crate::ptr::NonNull;
 use crate::sys::c;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 ///
 /// This uses `repr(transparent)` and has the representation of a host handle,
 /// so it can be used in FFI in places where a handle is passed as an argument,
-/// it is not captured or consumed, and it is never null.
+/// it is not captured or consumed.
 ///
 /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
 /// sometimes a valid handle value. See [here] for the full story.
 ///
+/// And, it *may* have the value `NULL` (0), which can occur when consoles are
+/// detached from processes, or when `windows_subsystem` is used.
+///
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
 #[derive(Copy, Clone)]
 #[repr(transparent)]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct BorrowedHandle<'handle> {
-    handle: NonNull<c_void>,
+    handle: RawHandle,
     _phantom: PhantomData<&'handle OwnedHandle>,
 }
 
@@ -38,14 +39,11 @@ pub struct BorrowedHandle<'handle> {
 ///
 /// This closes the handle on drop.
 ///
-/// This uses `repr(transparent)` and has the representation of a host handle,
-/// so it can be used in FFI in places where a handle is passed as a consumed
-/// argument or returned as an owned value, and is never null.
-///
 /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
-/// sometimes a valid handle value. See [here] for the full story. For APIs
-/// like `CreateFileW` which report errors with `INVALID_HANDLE_VALUE` instead
-/// of null, use [`HandleOrInvalid`] instead of `Option<OwnedHandle>`.
+/// sometimes a valid handle value. See [here] for the full story.
+///
+/// And, it *may* have the value `NULL` (0), which can occur when consoles are
+/// detached from processes, or when `windows_subsystem` is used.
 ///
 /// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such,
 /// it must not be used with handles to open registry keys which need to be
@@ -55,12 +53,31 @@ pub struct BorrowedHandle<'handle> {
 /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
 ///
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
-#[repr(transparent)]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct OwnedHandle {
-    handle: NonNull<c_void>,
+    handle: RawHandle,
 }
 
+/// FFI type for handles in return values or out parameters, where `NULL` is used
+/// as a sentry value to indicate errors, such as in the return value of `CreateThread`. This uses
+/// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
+/// FFI declarations.
+///
+/// The only thing you can usefully do with a `HandleOrNull` is to convert it into an
+/// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
+/// `NULL`. This ensures that such FFI calls cannot start using the handle without
+/// checking for `NULL` first.
+///
+/// This type concerns any value other than `NULL` to be valid, including `INVALID_HANDLE_VALUE`.
+/// This is because APIs that use `NULL` as their sentry value don't treat `INVALID_HANDLE_VALUE`
+/// as special.
+///
+/// If this holds a valid handle, it will close the handle on drop.
+#[repr(transparent)]
+#[unstable(feature = "io_safety", issue = "87074")]
+#[derive(Debug)]
+pub struct HandleOrNull(OwnedHandle);
+
 /// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
 /// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
 /// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
@@ -71,11 +88,15 @@ pub struct OwnedHandle {
 /// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without
 /// checking for `INVALID_HANDLE_VALUE` first.
 ///
+/// This type concerns any value other than `INVALID_HANDLE_VALUE` to be valid, including `NULL`.
+/// This is because APIs that use `INVALID_HANDLE_VALUE` as their sentry value may return `NULL`
+/// under `windows_subsystem = "windows"` or other situations where I/O devices are detached.
+///
 /// If this holds a valid handle, it will close the handle on drop.
 #[repr(transparent)]
 #[unstable(feature = "io_safety", issue = "87074")]
 #[derive(Debug)]
-pub struct HandleOrInvalid(Option<OwnedHandle>);
+pub struct HandleOrInvalid(OwnedHandle);
 
 // The Windows [`HANDLE`] type may be transferred across and shared between
 // thread boundaries (despite containing a `*mut void`, which in general isn't
@@ -83,9 +104,11 @@ pub struct OwnedHandle {
 //
 // [`HANDLE`]: std::os::windows::raw::HANDLE
 unsafe impl Send for OwnedHandle {}
+unsafe impl Send for HandleOrNull {}
 unsafe impl Send for HandleOrInvalid {}
 unsafe impl Send for BorrowedHandle<'_> {}
 unsafe impl Sync for OwnedHandle {}
+unsafe impl Sync for HandleOrNull {}
 unsafe impl Sync for HandleOrInvalid {}
 unsafe impl Sync for BorrowedHandle<'_> {}
 
@@ -95,18 +118,29 @@ impl BorrowedHandle<'_> {
     /// # Safety
     ///
     /// The resource pointed to by `handle` must be a valid open handle, it
-    /// must remain open for the duration of the returned `BorrowedHandle`, and
-    /// it must not be null.
+    /// must remain open for the duration of the returned `BorrowedHandle`.
     ///
     /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
     /// sometimes a valid handle value. See [here] for the full story.
     ///
+    /// And, it *may* have the value `NULL` (0), which can occur when consoles are
+    /// detached from processes, or when `windows_subsystem` is used.
+    ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
     pub unsafe fn borrow_raw_handle(handle: RawHandle) -> Self {
-        assert!(!handle.is_null());
-        Self { handle: NonNull::new_unchecked(handle), _phantom: PhantomData }
+        Self { handle, _phantom: PhantomData }
+    }
+}
+
+impl TryFrom<HandleOrNull> for OwnedHandle {
+    type Error = ();
+
+    #[inline]
+    fn try_from(handle_or_null: HandleOrNull) -> Result<Self, ()> {
+        let owned_handle = handle_or_null.0;
+        if owned_handle.handle.is_null() { Err(()) } else { Ok(owned_handle) }
     }
 }
 
@@ -115,44 +149,29 @@ impl TryFrom<HandleOrInvalid> for OwnedHandle {
 
     #[inline]
     fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, ()> {
-        // In theory, we ought to be able to assume that the pointer here is
-        // never null, use `OwnedHandle` rather than `Option<OwnedHandle>`, and
-        // obviate the the panic path here.  Unfortunately, Win32 documentation
-        // doesn't explicitly guarantee this anywhere.
-        //
-        // APIs like [`CreateFileW`] itself have `HANDLE` arguments where a
-        // null handle indicates an absent value, which wouldn't work if null
-        // were a valid handle value, so it seems very unlikely that it could
-        // ever return null. But who knows?
-        //
-        // [`CreateFileW`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
-        let owned_handle = handle_or_invalid.0.expect("A `HandleOrInvalid` was null!");
-        if owned_handle.handle.as_ptr() == c::INVALID_HANDLE_VALUE {
-            Err(())
-        } else {
-            Ok(owned_handle)
-        }
+        let owned_handle = handle_or_invalid.0;
+        if owned_handle.handle == c::INVALID_HANDLE_VALUE { Err(()) } else { Ok(owned_handle) }
     }
 }
 
 impl AsRawHandle for BorrowedHandle<'_> {
     #[inline]
     fn as_raw_handle(&self) -> RawHandle {
-        self.handle.as_ptr()
+        self.handle
     }
 }
 
 impl AsRawHandle for OwnedHandle {
     #[inline]
     fn as_raw_handle(&self) -> RawHandle {
-        self.handle.as_ptr()
+        self.handle
     }
 }
 
 impl IntoRawHandle for OwnedHandle {
     #[inline]
     fn into_raw_handle(self) -> RawHandle {
-        let handle = self.handle.as_ptr();
+        let handle = self.handle;
         forget(self);
         handle
     }
@@ -161,9 +180,6 @@ fn into_raw_handle(self) -> RawHandle {
 impl FromRawHandle for OwnedHandle {
     /// Constructs a new instance of `Self` from the given raw handle.
     ///
-    /// Use `HandleOrInvalid` instead of `Option<OwnedHandle>` for APIs that
-    /// use `INVALID_HANDLE_VALUE` to indicate failure.
-    ///
     /// # Safety
     ///
     /// The resource pointed to by `handle` must be open and suitable for
@@ -180,8 +196,28 @@ impl FromRawHandle for OwnedHandle {
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     unsafe fn from_raw_handle(handle: RawHandle) -> Self {
-        assert!(!handle.is_null());
-        Self { handle: NonNull::new_unchecked(handle) }
+        Self { handle }
+    }
+}
+
+impl FromRawHandle for HandleOrNull {
+    /// Constructs a new instance of `Self` from the given `RawHandle` returned
+    /// from a Windows API that uses null to indicate failure, such as
+    /// `CreateThread`.
+    ///
+    /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that
+    /// use `INVALID_HANDLE_VALUE` to indicate failure.
+    ///
+    /// # Safety
+    ///
+    /// The resource pointed to by `handle` must be either open and otherwise
+    /// unowned, or null. Note that not all Windows APIs use null for errors;
+    /// see [here] for the full story.
+    ///
+    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
+    #[inline]
+    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
+        Self(OwnedHandle::from_raw_handle(handle))
     }
 }
 
@@ -190,21 +226,20 @@ impl FromRawHandle for HandleOrInvalid {
     /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
     /// failure, such as `CreateFileW`.
     ///
-    /// Use `Option<OwnedHandle>` instead of `HandleOrInvalid` for APIs that
+    /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that
     /// use null to indicate failure.
     ///
     /// # Safety
     ///
     /// The resource pointed to by `handle` must be either open and otherwise
-    /// unowned, or equal to `INVALID_HANDLE_VALUE` (-1). It must not be null.
-    /// Note that not all Windows APIs use `INVALID_HANDLE_VALUE` for errors;
-    /// see [here] for the full story.
+    /// unowned, null, or equal to `INVALID_HANDLE_VALUE` (-1). Note that not
+    /// all Windows APIs use `INVALID_HANDLE_VALUE` for errors; see [here] for
+    /// the full story.
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     unsafe fn from_raw_handle(handle: RawHandle) -> Self {
-        // We require non-null here to catch errors earlier.
-        Self(Some(OwnedHandle::from_raw_handle(handle)))
+        Self(OwnedHandle::from_raw_handle(handle))
     }
 }
 
@@ -212,7 +247,7 @@ impl Drop for OwnedHandle {
     #[inline]
     fn drop(&mut self) {
         unsafe {
-            let _ = c::CloseHandle(self.handle.as_ptr());
+            let _ = c::CloseHandle(self.handle);
         }
     }
 }
index 9cc7fc2f0352e6e09b2fa7ab9565fc3936bc165a..b4dab41f06632f8b3cbb09421d4a9c4974c5bb91 100644 (file)
@@ -1417,6 +1417,11 @@ fn from(file: fs::File) -> Stdio {
 ///
 /// [`status`]: Command::status
 /// [`wait`]: Child::wait
+//
+// We speak slightly loosely (here and in various other places in the stdlib docs) about `exit`
+// vs `_exit`.  Naming of Unix system calls is not standardised across Unices, so terminology is a
+// matter of convention and tradition.  For clarity we usually speak of `exit`, even when we might
+// mean an underlying system call such as `_exit`.
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ExitStatus(imp::ExitStatus);
index 3526440fb85f02a1d70348bf67326611199537c2..3205f0db85fc34896506015b54c31ebdc294b8bc 100644 (file)
@@ -4,17 +4,15 @@
 pub mod sockets;
 pub use self::fs::*;
 
-pub const SOLID_BP_PROGRAM_EXITED: usize = 15;
-pub const SOLID_BP_CSABORT: usize = 16;
-
 #[inline(always)]
 pub fn breakpoint_program_exited(tid: usize) {
     unsafe {
         match () {
+            // SOLID_BP_PROGRAM_EXITED = 15
             #[cfg(target_arch = "arm")]
-            () => asm!("bkpt #{}", const SOLID_BP_PROGRAM_EXITED, in("r0") tid),
+            () => asm!("bkpt #15", in("r0") tid),
             #[cfg(target_arch = "aarch64")]
-            () => asm!("hlt #{}", const SOLID_BP_PROGRAM_EXITED, in("x0") tid),
+            () => asm!("hlt #15", in("x0") tid),
         }
     }
 }
@@ -23,10 +21,11 @@ pub fn breakpoint_program_exited(tid: usize) {
 pub fn breakpoint_abort() {
     unsafe {
         match () {
+            // SOLID_BP_CSABORT = 16
             #[cfg(target_arch = "arm")]
-            () => asm!("bkpt #{}", const SOLID_BP_CSABORT),
+            () => asm!("bkpt #16"),
             #[cfg(target_arch = "aarch64")]
-            () => asm!("hlt #{}", const SOLID_BP_CSABORT),
+            () => asm!("hlt #16"),
         }
     }
 }
index 99013efb495d095d681d1f60fbeb1762e11074e6..3bf1493f3b8cbd6860cadddd0f7f44789b47d95d 100644 (file)
@@ -166,6 +166,12 @@ struct clone_args {
             fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long
         }
 
+        // Bypassing libc for `clone3` can make further libc calls unsafe,
+        // so we use it sparingly for now. See #89522 for details.
+        // Some tools (e.g. sandboxing tools) may also expect `fork`
+        // rather than `clone3`.
+        let want_clone3_pidfd = self.get_create_pidfd();
+
         // If we fail to create a pidfd for any reason, this will
         // stay as -1, which indicates an error.
         let mut pidfd: pid_t = -1;
@@ -173,14 +179,9 @@ fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long
         // Attempt to use the `clone3` syscall, which supports more arguments
         // (in particular, the ability to create a pidfd). If this fails,
         // we will fall through this block to a call to `fork()`
-        if HAS_CLONE3.load(Ordering::Relaxed) {
-            let mut flags = 0;
-            if self.get_create_pidfd() {
-                flags |= CLONE_PIDFD;
-            }
-
+        if want_clone3_pidfd && HAS_CLONE3.load(Ordering::Relaxed) {
             let mut args = clone_args {
-                flags,
+                flags: CLONE_PIDFD,
                 pidfd: &mut pidfd as *mut pid_t as u64,
                 child_tid: 0,
                 parent_tid: 0,
@@ -212,8 +213,8 @@ fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long
             }
         }
 
-        // If we get here, the 'clone3' syscall does not exist
-        // or we do not have permission to call it
+        // Generally, we just call `fork`. If we get here after wanting `clone3`,
+        // then the syscall does not exist or we do not have permission to call it.
         cvt(libc::fork()).map(|res| (res, pidfd))
     }
 
@@ -616,6 +617,9 @@ pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
 }
 
 /// Unix exit statuses
+//
+// This is not actually an "exit status" in Unix terminology.  Rather, it is a "wait status".
+// See the discussion in comments and doc comments for `std::process::ExitStatus`.
 #[derive(PartialEq, Eq, Clone, Copy)]
 pub struct ExitStatus(c_int);
 
index 6f4863057aba431b0635eb11a4671e335e573913..b99eb2e553f08908effdf7385961767f75b30c88 100644 (file)
@@ -275,6 +275,14 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
             target_os = "solaris",
             target_os = "illumos",
         ))] {
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            {
+                let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
+                if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
+                    let count = unsafe { libc::CPU_COUNT(&set) };
+                    return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) });
+                }
+            }
             match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
                 -1 => Err(io::Error::last_os_error()),
                 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
index 053f3e3ee583b9afbe4783715ad4892f80d88569..265f2194fef8d0ce03c61d1c2222828a7c823dde 100644 (file)
@@ -17,6 +17,7 @@ ignore = [
 
     # do not format submodules
     "library/backtrace",
+    "library/portable-simd",
     "library/stdarch",
     "compiler/rustc_codegen_cranelift",
     "compiler/rustc_codegen_gcc",
index d4875cfe1b066e31d74f4d1ed48fc67ace3d26d8..a799732adde9d7d7aafec92619738a5ff54ace15 100644 (file)
@@ -96,7 +96,8 @@ impl Step for RustcDocs {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/librustc")
+        let builder = run.builder;
+        run.path("rustc-docs").default_condition(builder.config.compiler_docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -106,9 +107,6 @@ fn make_run(run: RunConfig<'_>) {
     /// Builds the `rustc-docs` installer component.
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
-        if !builder.config.compiler_docs {
-            return None;
-        }
         builder.default_doc(&[]);
 
         let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
index 2804e7119fbc14e8418365082bb879b22861d299..f0f31c447bda43326b5a20642d5cfa09538d2be1 100644 (file)
@@ -529,7 +529,7 @@ impl Step for Rustc {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.krate("rustc-main").path("compiler").default_condition(builder.config.docs)
+        run.krate("rustc-main").path("compiler").default_condition(builder.config.compiler_docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -560,11 +560,6 @@ fn run(self, builder: &Builder<'_>) {
             })
             .collect::<Vec<_>>();
 
-        if !builder.config.compiler_docs && !builder.was_invoked_explicitly::<Self>() {
-            builder.info("\tskipping - compiler/librustdoc docs disabled");
-            return;
-        }
-
         // This is the intended out directory for compiler documentation.
         let out = builder.compiler_doc_out(target);
         t!(fs::create_dir_all(&out));
@@ -674,7 +669,8 @@ impl Step for $tool {
             const ONLY_HOSTS: bool = true;
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-                run.krate($should_run)
+                let builder = run.builder;
+                run.krate($should_run).default_condition(builder.config.compiler_docs)
             }
 
             fn make_run(run: RunConfig<'_>) {
@@ -705,11 +701,6 @@ fn run(self, builder: &Builder<'_>) {
 
                 let compiler = builder.compiler(stage, builder.config.build);
 
-                if !builder.config.compiler_docs && !builder.was_invoked_explicitly::<Self>() {
-                    builder.info("\tskipping - compiler/tool docs disabled");
-                    return;
-                }
-
                 // Build rustc docs so that we generate relative links.
                 builder.ensure(Rustc { stage, target });
 
index 8594fa42266b41306d242f59c65b27fc5ca732d0..22bf6b8a9d4dce99392222a591a10154fb821e7d 100644 (file)
@@ -763,7 +763,7 @@ impl Step for RustdocJSStd {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/test/rustdoc-js-std")
+        run.suite_path("src/test/rustdoc-js-std")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -783,6 +783,17 @@ fn run(self, builder: &Builder<'_>) {
                 .arg(builder.doc_out(self.target))
                 .arg("--test-folder")
                 .arg(builder.src.join("src/test/rustdoc-js-std"));
+            for path in &builder.paths {
+                if let Some(p) =
+                    util::is_valid_test_suite_arg(path, "src/test/rustdoc-js-std", builder)
+                {
+                    if !p.ends_with(".js") {
+                        eprintln!("A non-js file was given: `{}`", path.display());
+                        panic!("Cannot run rustdoc-js-std tests");
+                    }
+                    command.arg("--test-file").arg(path);
+                }
+            }
             builder.ensure(crate::doc::Std { target: self.target, stage: builder.top_stage });
             builder.run(&mut command);
         } else {
@@ -803,7 +814,7 @@ impl Step for RustdocJSNotStd {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/test/rustdoc-js")
+        run.suite_path("src/test/rustdoc-js")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -938,8 +949,12 @@ fn run(self, builder: &Builder<'_>) {
             .arg("--tests-folder")
             .arg(builder.build.src.join("src/test/rustdoc-gui"));
         for path in &builder.paths {
-            if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
-                if name.ends_with(".goml") {
+            if let Some(p) = util::is_valid_test_suite_arg(path, "src/test/rustdoc-gui", builder) {
+                if !p.ends_with(".goml") {
+                    eprintln!("A non-goml file was given: `{}`", path.display());
+                    panic!("Cannot run rustdoc-gui tests");
+                }
+                if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
                     command.arg("--file").arg(name);
                 }
             }
@@ -1416,35 +1431,7 @@ fn run(self, builder: &Builder<'_>) {
         // Get test-args by striping suite path
         let mut test_args: Vec<&str> = paths
             .iter()
-            .map(|p| match p.strip_prefix(".") {
-                Ok(path) => path,
-                Err(_) => p,
-            })
-            .filter(|p| p.starts_with(suite_path))
-            .filter(|p| {
-                let exists = p.is_dir() || p.is_file();
-                if !exists {
-                    if let Some(p) = p.to_str() {
-                        builder.info(&format!(
-                            "Warning: Skipping \"{}\": not a regular file or directory",
-                            p
-                        ));
-                    }
-                }
-                exists
-            })
-            .filter_map(|p| {
-                // Since test suite paths are themselves directories, if we don't
-                // specify a directory or file, we'll get an empty string here
-                // (the result of the test suite directory without its suite prefix).
-                // Therefore, we need to filter these out, as only the first --test-args
-                // flag is respected, so providing an empty --test-args conflicts with
-                // any following it.
-                match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
-                    Some(s) if !s.is_empty() => Some(s),
-                    _ => None,
-                }
-            })
+            .filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder))
             .collect();
 
         test_args.append(&mut builder.config.cmd.test_args());
index af6f4bb0e5fcba19c98240a9bdbf80cb8dcad5ef..1317c3f9839757432106992f801522b25519fe3c 100644 (file)
@@ -286,7 +286,6 @@ macro_rules! bootstrap_tool {
         $name:ident, $path:expr, $tool_name:expr
         $(,is_external_tool = $external:expr)*
         $(,is_unstable_tool = $unstable:expr)*
-        $(,features = $features:expr)*
         ;
     )+) => {
         #[derive(Copy, PartialEq, Eq, Clone)]
@@ -349,12 +348,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
                     } else {
                         SourceType::InTree
                     },
-                    extra_features: {
-                        // FIXME(#60643): avoid this lint by using `_`
-                        let mut _tmp = Vec::new();
-                        $(_tmp.extend($features);)*
-                        _tmp
-                    },
+                    extra_features: vec![],
                 }).expect("expected to build -- essential tool")
             }
         }
index 112979b0bebc86f54047968bee5c7f37ec5eb8f4..57178aa382ffd789ac68a6fb9b9cf9051aceb7b8 100644 (file)
@@ -310,3 +310,35 @@ pub fn use_host_linker(target: TargetSelection) -> bool {
         || target.contains("fuchsia")
         || target.contains("bpf"))
 }
+
+pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
+    path: &'a Path,
+    suite_path: P,
+    builder: &Builder<'_>,
+) -> Option<&'a str> {
+    let suite_path = suite_path.as_ref();
+    let path = match path.strip_prefix(".") {
+        Ok(p) => p,
+        Err(_) => path,
+    };
+    if !path.starts_with(suite_path) {
+        return None;
+    }
+    let exists = path.is_dir() || path.is_file();
+    if !exists {
+        if let Some(p) = path.to_str() {
+            builder.info(&format!("Warning: Skipping \"{}\": not a regular file or directory", p));
+        }
+        return None;
+    }
+    // Since test suite paths are themselves directories, if we don't
+    // specify a directory or file, we'll get an empty string here
+    // (the result of the test suite directory without its suite prefix).
+    // Therefore, we need to filter these out, as only the first --test-args
+    // flag is respected, so providing an empty --test-args conflicts with
+    // any following it.
+    match path.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
+        Some(s) if !s.is_empty() => Some(s),
+        _ => None,
+    }
+}
index fd9299792852c9a368cb236748781852f75cdac6..5c5dbc5b196c9564422b3193264f3288d2a051ce 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fd9299792852c9a368cb236748781852f75cdac6
+Subproject commit 5c5dbc5b196c9564422b3193264f3288d2a051ce
index 7c0088ca744d293a5f4b1e2ac378e7c23d30fe55..27f4a84d3852e9416cae5861254fa53a825c56bd 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7c0088ca744d293a5f4b1e2ac378e7c23d30fe55
+Subproject commit 27f4a84d3852e9416cae5861254fa53a825c56bd
index 358e6a61d5f4f0496d0a81e70cdcd25d05307342..c6b4bf831e9a40aec34f53067d20634839a6778b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 358e6a61d5f4f0496d0a81e70cdcd25d05307342
+Subproject commit c6b4bf831e9a40aec34f53067d20634839a6778b
index 27f1ff5e440ef78828b68ab882b98e1b10d9af32..e9d45342d7a6c1def4731f1782d87ea317ba30c3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 27f1ff5e440ef78828b68ab882b98e1b10d9af32
+Subproject commit e9d45342d7a6c1def4731f1782d87ea317ba30c3
index b06008731af0f7d07cd0614e820c8276dfed1c18..196ef69aa68f2cef44f37566ee7db37daf00301b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b06008731af0f7d07cd0614e820c8276dfed1c18
+Subproject commit 196ef69aa68f2cef44f37566ee7db37daf00301b
index 3fa91bb51f02fb7d8c0ee8d2a6fac50c6aa410da..eb18185945387cbaf5de34a8cfc6335ccfc89c9d 100644 (file)
@@ -1,6 +1,7 @@
 # The Rustdoc Book
 
 - [What is rustdoc?](what-is-rustdoc.md)
+- [How to read rustdoc output](how-to-read-rustdoc.md)
 - [How to write documentation](how-to-write-documentation.md)
 - [What to include (and exclude)](what-to-include.md)
 - [Command-line arguments](command-line-arguments.md)
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
new file mode 100644 (file)
index 0000000..99724d8
--- /dev/null
@@ -0,0 +1,107 @@
+# How to read rustdoc output
+
+Rustdoc's HTML output includes a friendly and useful navigation interface which
+makes it easier for users to navigate and understand your code.
+This chapter covers the major features of that interface,
+and is a great starting point for documentation authors and users alike.
+
+## Structure
+
+The `rustdoc` output is divided into three sections.
+Along the left side of each page is a quick navigation bar,
+which shows contextual information about the current entry.
+The rest of the page is taken up by the search interface at the top
+and the documentation for the current item below that.
+
+## The Item Documentation
+
+The majority of the screen is taken up with the documentation text for the item
+currently being viewed.
+At the top is some at-a-glance info and controls:
+
+- the type and name of the item,
+  such as "Struct `std::time::Duration`",
+- a button to copy the item's path to the clipboard,
+  which is a clipboard item
+- a button to collapse or expand the top-level documentation for that item
+  (`[+]` or `[-]`),
+- a link to the source code (`[src]`),
+  if [configured](the-doc-attribute.html#html_no_source),
+  and present (the source may not be available if
+  the documentation was created with `cargo doc --no-deps`),
+- and the version in which the item became stable,
+  if it's a stable item in the standard library.
+
+Below this is the main documentation for the item,
+including a definition or function signature if appropriate,
+followed by a list of fields or variants for Rust types.
+Finally, the page lists associated functions and trait implementations,
+including automatic and blanket implementations that `rustdoc` knows about.
+
+### Navigation
+
+Subheadings, variants, fields, and many other things in this documentation
+are anchors and can be clicked on and deep-linked to,
+which is a great way to communicate exactly what you're talking about.
+The typograpical character "§" appears next to lines with anchors on them
+when hovered or given keyboard focus.
+
+## The Navigation Bar
+
+For example, when looking at documentation for the crate root,
+it shows all the crates documented in the documentation bundle,
+and quick links to the modules, structs, traits, functions, and macros available
+from the current crate.
+At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url)
+alongside the current crate's name and version,
+or the current item whose documentation is being displayed.
+
+## The Theme Picker and Search Interface
+
+When viewing `rustdoc`'s output in a browser with JavaScript enabled,
+a dynamic interface appears at the top of the page.
+To the left is the theme picker, denoted with a paint-brush icon,
+and the search interface, help screen, and options appear to the right of that.
+
+### The Theme Picker
+
+Clicking on the theme picker provides a list of themes -
+by default `ayu`, `light`, and `dark` -
+which are available for viewing.
+
+### The Search Interface
+
+Typing in the search bar instantly searches the available documentation for
+the string entered with a fuzzy matching algorithm that is tolerant of minor
+typos.
+
+By default, the search results give are "In Names",
+meaning that the fuzzy match is made against the names of items.
+Matching names are shown on the left, and the first few words of their
+descriptions are given on the right.
+By clicking an item, you will navigate to its particular documentation.
+
+There are two other sets of results, shown as tabs in the search results pane.
+"In Parameters" shows matches for the string in the types of parameters to
+functions, and "In Return Types" shows matches in the return types of functions.
+Both are very useful when looking for a function whose name you can't quite
+bring to mind when you know the type you have or want.
+
+When typing in the search bar, you can prefix your search term with a type
+followed by a colon (such as `mod:`) to restrict the results to just that
+kind of item. (The available items are listed in the help popup.)
+
+### Shortcuts
+
+Pressing `S` while focused elsewhere on the page will move focus to the
+search bar, and pressing `?` shows the help screen,
+which includes all these shortcuts and more.
+Pressing `T` focuses the theme picker.
+
+When the search results are focused,
+the left and right arrows move between tabs and the up and down arrows move
+among the results.
+Pressing the enter or return key opens the highlighted result.
+
+When looking at the documentation for an item, the plus and minus keys expand
+and collapse all sections in the document.
diff --git a/src/doc/unstable-book/src/compiler-flags/temps-dir.md b/src/doc/unstable-book/src/compiler-flags/temps-dir.md
new file mode 100644 (file)
index 0000000..e25011f
--- /dev/null
@@ -0,0 +1,10 @@
+# `temps-dir`
+
+--------------------
+
+The `-Ztemps-dir` compiler flag specifies the directory to write the
+intermediate files in. If not set, the output directory is used. This option is
+useful if you are running more than one instance of `rustc` (e.g. with different
+`--crate-type` settings), and you need to make sure they are not overwriting
+each other's intermediate files. No files are kept unless `-C save-temps=yes` is
+also set.
diff --git a/src/doc/unstable-book/src/language-features/type-changing-struct-update.md b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md
new file mode 100644 (file)
index 0000000..9909cf3
--- /dev/null
@@ -0,0 +1,33 @@
+# `type_changing_struct_update`
+
+The tracking issue for this feature is: [#86555]
+
+[#86555]: https://github.com/rust-lang/rust/issues/86555
+
+------------------------
+
+This implements [RFC2528]. When turned on, you can create instances of the same struct
+that have different generic type or lifetime parameters.
+
+[RFC2528]: https://github.com/rust-lang/rfcs/blob/master/text/2528-type-changing-struct-update-syntax.md
+
+```rust
+#![allow(unused_variables, dead_code)]
+#![feature(type_changing_struct_update)]
+
+fn main () {
+    struct Foo<T, U> {
+        field1: T,
+        field2: U,
+    }
+
+    let base: Foo<String, i32> = Foo {
+        field1: String::from("hello"),
+        field2: 1234,
+    };
+    let updated: Foo<f64, i32> = Foo {
+        field1: 3.14,
+        ..base
+    };
+}
+```
index 84fc6dcc33979d1605ab373e13cb00aa9bd622eb..fac55b978886cca41cd0020d5ee699450a624a82 100644 (file)
@@ -319,7 +319,7 @@ fn call_foo(arg: i32) -> i32 {
 
 Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`: the compiler will automatically insert the appropriate mangled symbol name into the assembly code.
 
-By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered.
+By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered.  Multiple `clobber_abi` arguments may be provided and all clobbers from all specified ABIs will be inserted.
 
 ## Register template modifiers
 
@@ -453,10 +453,10 @@ reg_spec := <register class> / "<explicit register>"
 operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
 reg_operand := dir_spec "(" reg_spec ")" operand_expr
 operand := reg_operand / "const" const_expr / "sym" path
-clobber_abi := "clobber_abi(" <abi> ")"
+clobber_abi := "clobber_abi(" <abi> *["," <abi>] [","] ")"
 option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
 options := "options(" option *["," option] [","] ")"
-asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," clobber_abi] *("," options) [","] ")"
+asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) *("," clobber_abi) *("," options) [","] ")"
 ```
 
 Inline assembly is currently supported on the following architectures:
@@ -562,9 +562,12 @@ Here is the list of currently supported register classes:
 | AArch64 | `vreg` | `v[0-31]` | `w` |
 | AArch64 | `vreg_low16` | `v[0-15]` | `x` |
 | AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers |
-| ARM | `reg` | `r[0-12]`, `r14` | `r` |
-| ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` |
+| ARM (ARM) | `reg` | `r[0-12]`, `r14` | `r` |
+| ARM (Thumb2) | `reg` | `r[0-12]`, `r14` | `r` |
+| ARM (Thumb1) | `reg` | `r[0-7]` | `r` |
 | ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` |
+| ARM (Thumb2) | `reg_thumb` | `r[0-7]` | `l` |
+| ARM (Thumb1) | `reg_thumb` | `r[0-7]` | `l` |
 | ARM | `sreg` | `s[0-31]` | `t` |
 | ARM | `sreg_low16` | `s[0-15]` | `x` |
 | ARM | `dreg` | `d[0-31]` | `w` |
@@ -799,6 +802,8 @@ As stated in the previous section, passing an input value smaller than the regis
 
 The `clobber_abi` keyword can be used to apply a default set of clobbers to an `asm` block. This will automatically insert the necessary clobber constraints as needed for calling a function with a particular calling convention: if the calling convention does not fully preserve the value of a register across a call then a `lateout("reg") _` is implicitly added to the operands list.
 
+`clobber_abi` may be specified any number of times. It will insert a clobber for all unique registers in the union of all specified calling conventions.
+
 Generic register class outputs are disallowed by the compiler when `clobber_abi` is used: all outputs must specify an explicit register. Explicit register outputs have precedence over the implicit clobbers inserted by `clobber_abi`: a clobber will only be inserted for a register if that register is not used as an output.
 The following ABIs can be used with `clobber_abi`:
 
index 146d17b4638c8357fcdac18ace09d2209836d299..3f8e165841d1421bb906720da5f8fc2171c4c26d 100644 (file)
@@ -75,7 +75,7 @@ are concatenated into one or assembled separately.
 constants defined in Rust to be used in assembly code:
 
 ```rust,no_run
-#![feature(global_asm)]
+#![feature(global_asm, asm_const)]
 # #[cfg(any(target_arch="x86", target_arch="x86_64"))]
 # mod x86 {
 const C: i32 = 1234;
@@ -96,7 +96,7 @@ override this by adding `options(att_syntax)` at the end of the macro
 arguments list:
 
 ```rust,no_run
-#![feature(global_asm)]
+#![feature(global_asm, asm_const)]
 # #[cfg(any(target_arch="x86", target_arch="x86_64"))]
 # mod x86 {
 global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
index ba701f42c660ba7606ada806d4e32c56910f3ddc..2ccf17387d1c701febec22a676ea264bd07bb845 100644 (file)
@@ -76,17 +76,17 @@ fn generate_for_trait(
             new_generics
         });
 
-        let negative_polarity;
+        let polarity;
         let new_generics = match result {
             AutoTraitResult::PositiveImpl(new_generics) => {
-                negative_polarity = false;
+                polarity = ty::ImplPolarity::Positive;
                 if discard_positive_impl {
                     return None;
                 }
                 new_generics
             }
             AutoTraitResult::NegativeImpl => {
-                negative_polarity = true;
+                polarity = ty::ImplPolarity::Negative;
 
                 // For negative impls, we use the generic params, but *not* the predicates,
                 // from the original type. Otherwise, the displayed impl appears to be a
@@ -115,15 +115,13 @@ fn generate_for_trait(
             visibility: Inherited,
             def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
             kind: box ImplItem(Impl {
-                span: Span::dummy(),
                 unsafety: hir::Unsafety::Normal,
                 generics: new_generics,
                 trait_: Some(trait_ref.clean(self.cx)),
                 for_: ty.clean(self.cx),
                 items: Vec::new(),
-                negative_polarity,
-                synthetic: true,
-                blanket_impl: None,
+                polarity,
+                kind: ImplKind::Auto,
             }),
             cfg: None,
         })
index 843dda324da7fb75842b6ca3457f17f1b69bdcdc..f44589f60675f5dbe8bb38c358121be812d540d1 100644 (file)
@@ -106,7 +106,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     visibility: Inherited,
                     def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
                     kind: box ImplItem(Impl {
-                        span: Span::new(self.cx.tcx.def_span(impl_def_id)),
                         unsafety: hir::Unsafety::Normal,
                         generics: (
                             self.cx.tcx.generics_of(impl_def_id),
@@ -122,11 +121,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             .tcx
                             .associated_items(impl_def_id)
                             .in_definition_order()
-                            .collect::<Vec<_>>()
-                            .clean(self.cx),
-                        negative_polarity: false,
-                        synthetic: false,
-                        blanket_impl: Some(box trait_ref.self_ty().clean(self.cx)),
+                            .map(|x| x.clean(self.cx))
+                            .collect::<Vec<_>>(),
+                        polarity: ty::ImplPolarity::Positive,
+                        kind: ImplKind::Blanket(box trait_ref.self_ty().clean(self.cx)),
                     }),
                     cfg: None,
                 });
index cb70f465f62b13aaba04acc7dd9cf06f9fa46277..4a8a316037961fcd056d0aa7b91e876bb24471b0 100644 (file)
@@ -14,7 +14,9 @@
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
 
-use crate::clean::{self, utils, Attributes, AttributesExt, ItemId, NestedAttributesExt, Type};
+use crate::clean::{
+    self, utils, Attributes, AttributesExt, ImplKind, ItemId, NestedAttributesExt, Type,
+};
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
 
@@ -242,7 +244,7 @@ fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
     clean::Enum {
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
         variants_stripped: false,
-        variants: cx.tcx.adt_def(did).variants.clean(cx),
+        variants: cx.tcx.adt_def(did).variants.iter().map(|v| v.clean(cx)).collect(),
     }
 }
 
@@ -253,7 +255,7 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
     clean::Struct {
         struct_type: variant.ctor_kind,
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
-        fields: variant.fields.clean(cx),
+        fields: variant.fields.iter().map(|x| x.clean(cx)).collect(),
         fields_stripped: false,
     }
 }
@@ -262,11 +264,9 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
     let predicates = cx.tcx.explicit_predicates_of(did);
     let variant = cx.tcx.adt_def(did).non_enum_variant();
 
-    clean::Union {
-        generics: (cx.tcx.generics_of(did), predicates).clean(cx),
-        fields: variant.fields.clean(cx),
-        fields_stripped: false,
-    }
+    let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
+    let fields = variant.fields.iter().map(|x| x.clean(cx)).collect();
+    clean::Union { generics, fields, fields_stripped: false }
 }
 
 fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::Typedef {
@@ -435,7 +435,7 @@ fn merge_attrs(
             tcx.associated_items(did)
                 .in_definition_order()
                 .filter_map(|item| {
-                    if associated_trait.is_some() || item.vis == ty::Visibility::Public {
+                    if associated_trait.is_some() || item.vis.is_public() {
                         Some(item.clean(cx))
                     } else {
                         None
@@ -446,7 +446,7 @@ fn merge_attrs(
         ),
     };
     let polarity = tcx.impl_polarity(did);
-    let trait_ = associated_trait.clean(cx);
+    let trait_ = associated_trait.map(|t| t.clean(cx));
     if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
@@ -490,15 +490,13 @@ fn merge_attrs(
         did,
         None,
         clean::ImplItem(clean::Impl {
-            span: clean::types::rustc_span(did, cx.tcx),
             unsafety: hir::Unsafety::Normal,
             generics,
             trait_,
             for_,
             items: trait_items,
-            negative_polarity: polarity.clean(cx),
-            synthetic: false,
-            blanket_impl: None,
+            polarity,
+            kind: ImplKind::Normal,
         }),
         box merged_attrs,
         cx,
@@ -517,7 +515,7 @@ fn build_module(
     // two namespaces, so the target may be listed twice. Make sure we only
     // visit each node at most once.
     for &item in cx.tcx.item_children(did).iter() {
-        if item.vis == ty::Visibility::Public {
+        if item.vis.is_public() {
             let res = item.res.expect_non_local();
             if let Some(def_id) = res.mod_def_id() {
                 if did == def_id || !visited.insert(def_id) {
index 9ea3112f178be2ad51a9fc098121dd6237546685..a44641f4488e8aae4234608bdf8f740a2f159eac 100644 (file)
@@ -16,7 +16,6 @@
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
@@ -34,7 +33,6 @@
 use std::collections::hash_map::Entry;
 use std::default::Default;
 use std::hash::Hash;
-use std::rc::Rc;
 use std::{mem, vec};
 
 use crate::core::{self, DocContext, ImplTraitParam};
     fn clean(&self, cx: &mut DocContext<'_>) -> T;
 }
 
-impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Vec<U> {
-        self.iter().map(|x| x.clean(cx)).collect()
-    }
-}
-
-impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> IndexVec<V, U> {
-        self.iter().map(|x| x.clean(cx)).collect()
-    }
-}
-
-impl<T: Clean<U>, U> Clean<U> for &T {
-    fn clean(&self, cx: &mut DocContext<'_>) -> U {
-        (**self).clean(cx)
-    }
-}
-
-impl<T: Clean<U>, U> Clean<U> for Rc<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> U {
-        (**self).clean(cx)
-    }
-}
-
-impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Option<U> {
-        self.as_ref().map(|v| v.clean(cx))
-    }
-}
-
 impl Clean<Item> for doctree::Module<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let mut items: Vec<Item> = vec![];
@@ -222,7 +190,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
             | rl::Region::Free(_, node_id),
         ) = def
         {
-            if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {
+            if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
                 return lt;
             }
         }
@@ -287,14 +255,14 @@ fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
                     .collect();
                 WherePredicate::BoundPredicate {
                     ty: wbp.bounded_ty.clean(cx),
-                    bounds: wbp.bounds.clean(cx),
+                    bounds: wbp.bounds.iter().map(|x| x.clean(cx)).collect(),
                     bound_params,
                 }
             }
 
             hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
                 lifetime: wrp.lifetime.clean(cx),
-                bounds: wrp.bounds.clean(cx),
+                bounds: wrp.bounds.iter().map(|x| x.clean(cx)).collect(),
             },
 
             hir::WherePredicate::EqPredicate(ref wrp) => {
@@ -459,8 +427,8 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
                 self.name.ident().name,
                 GenericParamDefKind::Type {
                     did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
-                    bounds: self.bounds.clean(cx),
-                    default: default.clean(cx).map(Box::new),
+                    bounds: self.bounds.iter().map(|x| x.clean(cx)).collect(),
+                    default: default.map(|t| t.clean(cx)).map(Box::new),
                     synthetic,
                 },
             ),
@@ -530,8 +498,10 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
         }
         params.extend(impl_trait_params);
 
-        let mut generics =
-            Generics { params, where_predicates: self.where_clause.predicates.clean(cx) };
+        let mut generics = Generics {
+            params,
+            where_predicates: self.where_clause.predicates.iter().map(|x| x.clean(cx)).collect(),
+        };
 
         // Some duplicates are generated for ?Sized bounds between type params and where
         // predicates. The point in here is to move the bounds definitions from type params
@@ -900,7 +870,7 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
         PolyTrait {
             trait_: self.trait_ref.clean(cx),
-            generic_params: self.bound_generic_params.clean(cx),
+            generic_params: self.bound_generic_params.iter().map(|x| x.clean(cx)).collect(),
         }
     }
 }
@@ -924,7 +894,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                 }
                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
                     let (generics, decl) = enter_impl_trait(cx, |cx| {
-                        (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
+                        (self.generics.clean(cx), (sig.decl, names).clean(cx))
                     });
                     let mut t = Function { header: sig.header, decl, generics };
                     if t.header.constness == hir::Constness::Const
@@ -935,7 +905,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                     TyMethodItem(t)
                 }
                 hir::TraitItemKind::Type(bounds, ref default) => {
-                    AssocTypeItem(bounds.clean(cx), default.clean(cx))
+                    let bounds = bounds.iter().map(|x| x.clean(cx)).collect();
+                    let default = default.map(|t| t.clean(cx));
+                    AssocTypeItem(bounds, default)
                 }
             };
             let what_rustc_thinks =
@@ -1127,7 +1099,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
                         None
                     };
 
-                    AssocTypeItem(bounds, ty.clean(cx))
+                    AssocTypeItem(bounds, ty.map(|t| t.clean(cx)))
                 } else {
                     // FIXME: when could this happen? Associated items in inherent impls?
                     let type_ = tcx.type_of(self.def_id).clean(cx);
@@ -1148,7 +1120,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
 }
 
 fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
-    use rustc_hir::GenericParamCount;
     let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
     let qpath = match kind {
         hir::TyKind::Path(qpath) => qpath,
@@ -1158,7 +1129,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     match qpath {
         hir::QPath::Resolved(None, ref path) => {
             if let Res::Def(DefKind::TyParam, did) = path.res {
-                if let Some(new_ty) = cx.ty_substs.get(&did).cloned() {
+                if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
                     return new_ty;
                 }
                 if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
@@ -1166,97 +1137,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 }
             }
 
-            let mut alias = None;
-            if let Res::Def(DefKind::TyAlias, def_id) = path.res {
-                // Substitute private type aliases
-                if let Some(def_id) = def_id.as_local() {
-                    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
-                    if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
-                        alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
-                    }
-                }
-            };
-
-            if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
-                let provided_params = &path.segments.last().expect("segments were empty");
-                let mut ty_substs = FxHashMap::default();
-                let mut lt_substs = FxHashMap::default();
-                let mut ct_substs = FxHashMap::default();
-                let generic_args = provided_params.args();
-                {
-                    let mut indices: GenericParamCount = Default::default();
-                    for param in generics.params.iter() {
-                        match param.kind {
-                            hir::GenericParamKind::Lifetime { .. } => {
-                                let mut j = 0;
-                                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Lifetime(lt) => {
-                                        if indices.lifetimes == j {
-                                            return Some(lt);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(lt) = lifetime.cloned() {
-                                    let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                    let cleaned = if !lt.is_elided() {
-                                        lt.clean(cx)
-                                    } else {
-                                        self::types::Lifetime::elided()
-                                    };
-                                    lt_substs.insert(lt_def_id.to_def_id(), cleaned);
-                                }
-                                indices.lifetimes += 1;
-                            }
-                            hir::GenericParamKind::Type { ref default, .. } => {
-                                let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                let mut j = 0;
-                                let type_ = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Type(ty) => {
-                                        if indices.types == j {
-                                            return Some(ty);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(ty) = type_ {
-                                    ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
-                                } else if let Some(default) = *default {
-                                    ty_substs
-                                        .insert(ty_param_def_id.to_def_id(), default.clean(cx));
-                                }
-                                indices.types += 1;
-                            }
-                            hir::GenericParamKind::Const { .. } => {
-                                let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                let mut j = 0;
-                                let const_ = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Const(ct) => {
-                                        if indices.consts == j {
-                                            return Some(ct);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(ct) = const_ {
-                                    ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
-                                }
-                                // FIXME(const_generics_defaults)
-                                indices.consts += 1;
-                            }
-                        }
-                    }
-                }
-                return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
+            if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
+                expanded
+            } else {
+                let path = path.clean(cx);
+                resolve_type(cx, path)
             }
-            let path = path.clean(cx);
-            resolve_type(cx, path)
         }
         hir::QPath::Resolved(Some(ref qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
@@ -1269,7 +1155,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
             let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id();
             let trait_ = self::Path {
                 res: Res::Def(DefKind::Trait, trait_def),
-                segments: trait_segments.clean(cx),
+                segments: trait_segments.iter().map(|x| x.clean(cx)).collect(),
             };
             register_res(cx, trait_.res);
             Type::QPath {
@@ -1300,6 +1186,94 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     }
 }
 
+fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option<Type> {
+    let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
+    // Substitute private type aliases
+    let Some(def_id) = def_id.as_local() else { return None };
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+    let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
+        &cx.tcx.hir().expect_item(hir_id).kind
+    } else {
+        return None;
+    };
+    let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
+
+    let provided_params = &path.segments.last().expect("segments were empty");
+    let mut substs = FxHashMap::default();
+    let generic_args = provided_params.args();
+
+    let mut indices: hir::GenericParamCount = Default::default();
+    for param in generics.params.iter() {
+        match param.kind {
+            hir::GenericParamKind::Lifetime { .. } => {
+                let mut j = 0;
+                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Lifetime(lt) => {
+                        if indices.lifetimes == j {
+                            return Some(lt);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(lt) = lifetime.cloned() {
+                    let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                    let cleaned = if !lt.is_elided() {
+                        lt.clean(cx)
+                    } else {
+                        self::types::Lifetime::elided()
+                    };
+                    substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
+                }
+                indices.lifetimes += 1;
+            }
+            hir::GenericParamKind::Type { ref default, .. } => {
+                let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                let mut j = 0;
+                let type_ = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Type(ty) => {
+                        if indices.types == j {
+                            return Some(ty);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(ty) = type_ {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(ty.clean(cx)));
+                } else if let Some(default) = *default {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(default.clean(cx)));
+                }
+                indices.types += 1;
+            }
+            hir::GenericParamKind::Const { .. } => {
+                let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                let mut j = 0;
+                let const_ = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Const(ct) => {
+                        if indices.consts == j {
+                            return Some(ct);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(ct) = const_ {
+                    substs
+                        .insert(const_param_def_id.to_def_id(), SubstParam::Constant(ct.clean(cx)));
+                }
+                // FIXME(const_generics_defaults)
+                indices.consts += 1;
+            }
+        }
+    }
+
+    Some(cx.enter_alias(substs, |cx| ty.clean(cx)))
+}
+
 impl Clean<Type> for hir::Ty<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         use rustc_hir::*;
@@ -1335,11 +1309,11 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 let length = print_const(cx, ct.eval(cx.tcx, param_env));
                 Array(box ty.clean(cx), length)
             }
-            TyKind::Tup(tys) => Tuple(tys.clean(cx)),
+            TyKind::Tup(tys) => Tuple(tys.iter().map(|x| x.clean(cx)).collect()),
             TyKind::OpaqueDef(item_id, _) => {
                 let item = cx.tcx.hir().item(item_id);
                 if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
-                    ImplTrait(ty.bounds.clean(cx))
+                    ImplTrait(ty.bounds.iter().map(|x| x.clean(cx)).collect())
                 } else {
                     unreachable!()
                 }
@@ -1479,7 +1453,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
 
                 DynTrait(bounds, lifetime)
             }
-            ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx)),
+            ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty().clean(cx)).collect()),
 
             ty::Projection(ref data) => data.clean(cx),
 
@@ -1712,7 +1686,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
 
 impl Clean<Path> for hir::Path<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Path {
-        Path { res: self.res, segments: self.segments.clean(cx) }
+        Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() }
     }
 }
 
@@ -1722,24 +1696,24 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
             let output = self.bindings[0].ty().clean(cx);
             let output =
                 if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
-            GenericArgs::Parenthesized { inputs: self.inputs().clean(cx), output }
+            let inputs = self.inputs().iter().map(|x| x.clean(cx)).collect();
+            GenericArgs::Parenthesized { inputs, output }
         } else {
-            GenericArgs::AngleBracketed {
-                args: self
-                    .args
-                    .iter()
-                    .map(|arg| match arg {
-                        hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
-                            GenericArg::Lifetime(lt.clean(cx))
-                        }
-                        hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
-                        hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
-                        hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
-                        hir::GenericArg::Infer(_inf) => GenericArg::Infer,
-                    })
-                    .collect(),
-                bindings: self.bindings.clean(cx),
-            }
+            let args = self
+                .args
+                .iter()
+                .map(|arg| match arg {
+                    hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
+                        GenericArg::Lifetime(lt.clean(cx))
+                    }
+                    hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
+                    hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
+                    hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
+                    hir::GenericArg::Infer(_inf) => GenericArg::Infer,
+                })
+                .collect();
+            let bindings = self.bindings.iter().map(|x| x.clean(cx)).collect();
+            GenericArgs::AngleBracketed { args, bindings }
         }
     }
 }
@@ -1753,7 +1727,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> PathSegment {
 impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
-            (self.generic_params.clean(cx), (&*self.decl, self.param_names).clean(cx))
+            let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect();
+            let decl = (self.decl, self.param_names).clean(cx);
+            (generic_params, decl)
         });
         BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
     }
@@ -1776,7 +1752,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                     kind: ConstantKind::Local { body: body_id, def_id },
                 }),
                 ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
-                    bounds: ty.bounds.clean(cx),
+                    bounds: ty.bounds.iter().map(|x| x.clean(cx)).collect(),
                     generics: ty.generics.clean(cx),
                 }),
                 ItemKind::TyAlias(hir_ty, ref generics) => {
@@ -1798,17 +1774,17 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                 }),
                 ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
                     generics: generics.clean(cx),
-                    bounds: bounds.clean(cx),
+                    bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
                 }),
                 ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
                     generics: generics.clean(cx),
-                    fields: variant_data.fields().clean(cx),
+                    fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
                     fields_stripped: false,
                 }),
                 ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
                     struct_type: CtorKind::from_hir(variant_data),
                     generics: generics.clean(cx),
-                    fields: variant_data.fields().clean(cx),
+                    fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
                     fields_stripped: false,
                 }),
                 ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
@@ -1817,7 +1793,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                     clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
                 }
                 ItemKind::Macro(ref macro_def) => MacroItem(Macro {
-                    source: display_macro_source(cx, name, macro_def, def_id, &item.vis),
+                    source: display_macro_source(cx, name, macro_def, def_id, item.vis),
                 }),
                 ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => {
                     let items = item_ids
@@ -1828,7 +1804,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                         unsafety,
                         items,
                         generics: generics.clean(cx),
-                        bounds: bounds.clean(cx),
+                        bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
                         is_auto: is_auto.clean(cx),
                     })
                 }
@@ -1856,22 +1832,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
     }
 }
 
-impl Clean<bool> for ty::ImplPolarity {
-    /// Returns whether the impl has negative polarity.
-    fn clean(&self, _: &mut DocContext<'_>) -> bool {
-        match self {
-            &ty::ImplPolarity::Positive |
-            // FIXME: do we want to do something else here?
-            &ty::ImplPolarity::Reservation => false,
-            &ty::ImplPolarity::Negative => true,
-        }
-    }
-}
-
 fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> {
     let tcx = cx.tcx;
     let mut ret = Vec::new();
-    let trait_ = impl_.of_trait.clean(cx);
+    let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx));
     let items =
         impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
     let def_id = tcx.hir().local_def_id(hir_id);
@@ -1889,15 +1853,13 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>
     });
     let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
         let kind = ImplItem(Impl {
-            span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx),
             unsafety: impl_.unsafety,
             generics: impl_.generics.clean(cx),
             trait_,
             for_,
             items,
-            negative_polarity: tcx.impl_polarity(def_id).clean(cx),
-            synthetic: false,
-            blanket_impl: None,
+            polarity: tcx.impl_polarity(def_id),
+            kind: ImplKind::Normal,
         });
         Item::from_hir_id_and_parts(hir_id, None, kind, cx)
     };
@@ -1919,7 +1881,7 @@ fn clean_extern_crate(
     // this is the ID of the crate itself
     let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
     let attrs = cx.tcx.hir().attrs(krate.hir_id());
-    let please_inline = krate.vis.node.is_pub()
+    let please_inline = cx.tcx.visibility(krate.def_id).is_public()
         && attrs.iter().any(|a| {
             a.has_name(sym::doc)
                 && match a.meta_item_list() {
@@ -1971,9 +1933,12 @@ fn clean_use_statement(
         return Vec::new();
     }
 
+    let visibility = cx.tcx.visibility(import.def_id);
     let attrs = cx.tcx.hir().attrs(import.hir_id());
     let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
-    let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore;
+    let pub_underscore = visibility.is_public() && name == kw::Underscore;
+    let current_mod = cx.tcx.parent_module_from_def_id(import.def_id);
+    let parent_mod = cx.tcx.parent_module_from_def_id(current_mod);
 
     if pub_underscore {
         if let Some(ref inline) = inline_attr {
@@ -1992,8 +1957,9 @@ fn clean_use_statement(
     // forcefully don't inline if this is not public or if the
     // #[doc(no_inline)] attribute is present.
     // Don't inline doc(hidden) imports so they can be stripped at a later stage.
-    let mut denied = !(import.vis.node.is_pub()
-        || (cx.render_options.document_private && import.vis.node.is_pub_restricted()))
+    let mut denied = !(visibility.is_public()
+        || (cx.render_options.document_private
+            && visibility.is_accessible_from(parent_mod.to_def_id(), cx.tcx)))
         || pub_underscore
         || attrs.iter().any(|a| {
             a.has_name(sym::doc)
@@ -2063,9 +2029,8 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
             let kind = match item.kind {
                 hir::ForeignItemKind::Fn(decl, names, ref generics) => {
                     let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
-                    let (generics, decl) = enter_impl_trait(cx, |cx| {
-                        (generics.clean(cx), (&*decl, &names[..]).clean(cx))
-                    });
+                    let (generics, decl) =
+                        enter_impl_trait(cx, |cx| (generics.clean(cx), (decl, names).clean(cx)));
                     ForeignFunctionItem(Function {
                         decl,
                         generics,
index 56ae43855de924718c08a49e5c85de296bfb4210..2dba52afcd9cd847203c001024e4cb157dc7aafa 100644 (file)
@@ -254,7 +254,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
                             as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
                         }
                         hir::ItemKind::Use(path, hir::UseKind::Single)
-                            if item.vis.node.is_pub() =>
+                            if tcx.visibility(id.def_id).is_public() =>
                         {
                             as_keyword(path.res.expect_non_local())
                                 .map(|(_, prim)| (id.def_id.to_def_id(), prim))
@@ -320,7 +320,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
                             as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
                         }
                         hir::ItemKind::Use(path, hir::UseKind::Single)
-                            if item.vis.node.is_pub() =>
+                            if tcx.visibility(id.def_id).is_public() =>
                         {
                             as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
                                 // Pretend the primitive is local.
@@ -391,12 +391,19 @@ impl Item {
             ItemKind::StrippedItem(k) => k,
             _ => &*self.kind,
         };
-        if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
-            kind
-        {
-            *span
-        } else {
-            self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
+        match kind {
+            ItemKind::ModuleItem(Module { span, .. }) => *span,
+            ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
+            ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
+                if let ItemId::Blanket { impl_id, .. } = self.def_id {
+                    rustc_span(impl_id, tcx)
+                } else {
+                    panic!("blanket impl item has non-blanket ID")
+                }
+            }
+            _ => {
+                self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
+            }
         }
     }
 
@@ -2165,15 +2172,13 @@ impl Constant {
 
 #[derive(Clone, Debug)]
 crate struct Impl {
-    crate span: Span,
     crate unsafety: hir::Unsafety,
     crate generics: Generics,
     crate trait_: Option<Path>,
     crate for_: Type,
     crate items: Vec<Item>,
-    crate negative_polarity: bool,
-    crate synthetic: bool,
-    crate blanket_impl: Option<Box<Type>>,
+    crate polarity: ty::ImplPolarity,
+    crate kind: ImplKind,
 }
 
 impl Impl {
@@ -2186,6 +2191,30 @@ impl Impl {
     }
 }
 
+#[derive(Clone, Debug)]
+crate enum ImplKind {
+    Normal,
+    Auto,
+    Blanket(Box<Type>),
+}
+
+impl ImplKind {
+    crate fn is_auto(&self) -> bool {
+        matches!(self, ImplKind::Auto)
+    }
+
+    crate fn is_blanket(&self) -> bool {
+        matches!(self, ImplKind::Blanket(_))
+    }
+
+    crate fn as_blanket_ty(&self) -> Option<&Type> {
+        match self {
+            ImplKind::Blanket(ty) => Some(ty),
+            _ => None,
+        }
+    }
+}
+
 #[derive(Clone, Debug)]
 crate struct Import {
     crate kind: ImportKind,
@@ -2250,3 +2279,32 @@ impl TypeBinding {
         }
     }
 }
+
+/// The type, lifetime, or constant that a private type alias's parameter should be
+/// replaced with when expanding a use of that type alias.
+///
+/// For example:
+///
+/// ```
+/// type PrivAlias<T> = Vec<T>;
+///
+/// pub fn public_fn() -> PrivAlias<i32> { vec![] }
+/// ```
+///
+/// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
+/// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
+crate enum SubstParam {
+    Type(Type),
+    Lifetime(Lifetime),
+    Constant(Constant),
+}
+
+impl SubstParam {
+    crate fn as_ty(&self) -> Option<&Type> {
+        if let Self::Type(ty) = self { Some(ty) } else { None }
+    }
+
+    crate fn as_lt(&self) -> Option<&Lifetime> {
+        if let Self::Lifetime(lt) = self { Some(lt) } else { None }
+    }
+}
index 2fae3163a1a1a4f19509091f6520929e04bf98f0..2fa7efcc6509b143e69b5192d06cf4bf8d507669 100644 (file)
@@ -430,8 +430,9 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
         | Res::NonMacroAttr(_)
         | Res::Err => return res.def_id(),
         Res::Def(
-            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst | OpaqueTy
-            | Field | LifetimeParam | GlobalAsm | Impl | Closure | Generator,
+            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst
+            | InlineConst | OpaqueTy | Field | LifetimeParam | GlobalAsm | Impl | Closure
+            | Generator,
             id,
         ) => return id,
     };
index b7251e8f57151cb3024ee2a40b77c2bb7dee9678..a331f4cf3e6e7c6e48e015ad67409019d07a6b65 100644 (file)
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_resolve as resolve;
+use rustc_resolve::Namespace::TypeNS;
 use rustc_session::config::{self, CrateType, ErrorOutputType};
 use rustc_session::lint;
 use rustc_session::DiagnosticOutput;
 use rustc_session::Session;
+use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 
 use std::cell::RefCell;
 use std::lazy::SyncLazy;
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
     crate active_extern_traits: FxHashSet<DefId>,
-    // The current set of type and lifetime substitutions,
+    // The current set of parameter substitutions,
     // for expanding type aliases at the HIR level:
-    /// Table `DefId` of type parameter -> substituted type
-    crate ty_substs: FxHashMap<DefId, clean::Type>,
-    /// Table `DefId` of lifetime parameter -> substituted lifetime
-    crate lt_substs: FxHashMap<DefId, clean::Lifetime>,
-    /// Table `DefId` of const parameter -> substituted const
-    crate ct_substs: FxHashMap<DefId, clean::Constant>,
+    /// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
+    crate substs: FxHashMap<DefId, clean::SubstParam>,
     /// Table synthetic type parameter for `impl Trait` in argument position -> bounds
     crate impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
     /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -104,25 +102,13 @@ impl<'tcx> DocContext<'tcx> {
 
     /// Call the closure with the given parameters set as
     /// the substitutions for a type alias' RHS.
-    crate fn enter_alias<F, R>(
-        &mut self,
-        ty_substs: FxHashMap<DefId, clean::Type>,
-        lt_substs: FxHashMap<DefId, clean::Lifetime>,
-        ct_substs: FxHashMap<DefId, clean::Constant>,
-        f: F,
-    ) -> R
+    crate fn enter_alias<F, R>(&mut self, substs: FxHashMap<DefId, clean::SubstParam>, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
     {
-        let (old_tys, old_lts, old_cts) = (
-            mem::replace(&mut self.ty_substs, ty_substs),
-            mem::replace(&mut self.lt_substs, lt_substs),
-            mem::replace(&mut self.ct_substs, ct_substs),
-        );
+        let old_substs = mem::replace(&mut self.substs, substs);
         let r = f(self);
-        self.ty_substs = old_tys;
-        self.lt_substs = old_lts;
-        self.ct_substs = old_cts;
+        self.substs = old_substs;
         r
     }
 
@@ -281,9 +267,9 @@ impl<'tcx> DocContext<'tcx> {
                 // Closures' tables come from their outermost function,
                 // as they are part of the same "inference environment".
                 // This avoids emitting errors for the parent twice (see similar code in `typeck_with_fallback`)
-                let outer_def_id = tcx.closure_base_def_id(def_id.to_def_id()).expect_local();
-                if outer_def_id != def_id {
-                    return tcx.typeck(outer_def_id);
+                let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
+                if typeck_root_def_id != def_id {
+                    return tcx.typeck(typeck_root_def_id);
                 }
 
                 let hir = tcx.hir();
@@ -299,13 +285,43 @@ impl<'tcx> DocContext<'tcx> {
 }
 
 crate fn create_resolver<'a>(
+    externs: config::Externs,
     queries: &Queries<'a>,
     sess: &Session,
 ) -> Rc<RefCell<interface::BoxedResolver>> {
     let (krate, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
     let resolver = resolver.clone();
 
-    crate::passes::collect_intra_doc_links::load_intra_link_crates(resolver, krate)
+    let resolver = crate::passes::collect_intra_doc_links::load_intra_link_crates(resolver, krate);
+
+    // FIXME: somehow rustdoc is still missing crates even though we loaded all
+    // the known necessary crates. Load them all unconditionally until we find a way to fix this.
+    // DO NOT REMOVE THIS without first testing on the reproducer in
+    // https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb
+    let extern_names: Vec<String> = externs
+        .iter()
+        .filter(|(_, entry)| entry.add_prelude)
+        .map(|(name, _)| name)
+        .cloned()
+        .collect();
+    resolver.borrow_mut().access(|resolver| {
+        sess.time("load_extern_crates", || {
+            for extern_name in &extern_names {
+                debug!("loading extern crate {}", extern_name);
+                if let Err(()) = resolver
+                    .resolve_str_path_error(
+                        DUMMY_SP,
+                        extern_name,
+                        TypeNS,
+                        LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
+                  ) {
+                    warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name)
+                  }
+            }
+        });
+    });
+
+    resolver
 }
 
 crate fn run_global_ctxt(
@@ -350,9 +366,7 @@ impl<'tcx> DocContext<'tcx> {
         param_env: ParamEnv::empty(),
         external_traits: Default::default(),
         active_extern_traits: Default::default(),
-        ty_substs: Default::default(),
-        lt_substs: Default::default(),
-        ct_substs: Default::default(),
+        substs: Default::default(),
         impl_trait_bounds: Default::default(),
         generated_synthetics: Default::default(),
         auto_traits: tcx
@@ -486,11 +500,13 @@ fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
         };
         if run {
             debug!("running pass {}", p.pass.name);
-            krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt));
+            krate = tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &mut ctxt));
         }
     }
 
-    ctxt.sess().abort_if_errors();
+    if tcx.sess.diagnostic().has_errors_or_lint_errors() {
+        rustc_errors::FatalError.raise();
+    }
 
     let render_options = ctxt.render_options;
     let mut cache = ctxt.cache;
index 9b32ad979e385572cdd3878cdae54ff712b1b811..c10eebf49fc8d657af5b333fcccf83af486d678d 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{ColorConfig, ErrorReported};
+use rustc_errors::{ColorConfig, ErrorReported, FatalError};
 use rustc_hir as hir;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::intravisit;
 
                 collector
             });
-            compiler.session().abort_if_errors();
+            if compiler.session().diagnostic().has_errors_or_lint_errors() {
+                FatalError.raise();
+            }
 
             let unused_extern_reports = collector.unused_extern_reports.clone();
             let compiling_test_count = collector.compiling_test_count.load(Ordering::SeqCst);
index 6b9c9a9669b1a4a4284e9ff6877f0b9e37221d5d..a929cd094f8c3bcb6417d1f35c937786540c4888 100644 (file)
@@ -228,7 +228,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         // Collect all the implementors of traits.
         if let clean::ImplItem(ref i) = *item.kind {
             if let Some(trait_) = &i.trait_ {
-                if i.blanket_impl.is_none() {
+                if !i.kind.is_blanket() {
                     self.cache
                         .implementors
                         .entry(trait_.def_id())
index 793db16faf38517dd5954e98b1bfaab9804bf425..3979d29b673fd3bd37a8fc6865b6b0ee3e46bcb0 100644 (file)
@@ -134,6 +134,7 @@ fn from(other: DefKind) -> Self {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::AnonConst
+            | DefKind::InlineConst
             | DefKind::OpaqueTy
             | DefKind::Field
             | DefKind::LifetimeParam
index c51bda60b73853b1142e2766aa156159fe1c85b6..4f2049132046d8a534a9c8e9069a15d836d5be84 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_target::spec::abi::Abi;
@@ -990,14 +991,15 @@ impl clean::Impl {
             }
 
             if let Some(ref ty) = self.trait_ {
-                if self.negative_polarity {
-                    write!(f, "!")?;
+                match self.polarity {
+                    ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {}
+                    ty::ImplPolarity::Negative => write!(f, "!")?,
                 }
                 fmt::Display::fmt(&ty.print(cx), f)?;
                 write!(f, " for ")?;
             }
 
-            if let Some(ref ty) = self.blanket_impl {
+            if let Some(ref ty) = self.kind.as_blanket_ty() {
                 fmt_type(ty, f, use_absolute, cx)?;
             } else {
                 fmt_type(&self.for_, f, use_absolute, cx)?;
index ff1bd5e7ff289565c06076f8f7437743e1427ec4..7aa950d905de14a4ef5f21bd20c69467a108d7ae 100644 (file)
@@ -26,7 +26,6 @@
 /// Builds the search index from the collected metadata
 crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<'tcx>) -> String {
     let mut defid_to_pathid = FxHashMap::default();
-    let mut crate_items = Vec::with_capacity(cache.search_index.len());
     let mut crate_paths = vec![];
 
     // Attach all orphan items to the type's definition if the type
 
     // Reduce `DefId` in paths into smaller sequential numbers,
     // and prune the paths that do not appear in the index.
-    let mut lastpath = String::new();
+    let mut lastpath = "";
     let mut lastpathid = 0usize;
 
-    for item in search_index {
-        item.parent_idx = item.parent.and_then(|defid| match defid_to_pathid.entry(defid) {
-            Entry::Occupied(entry) => Some(*entry.get()),
-            Entry::Vacant(entry) => {
-                let pathid = lastpathid;
-                entry.insert(pathid);
-                lastpathid += 1;
+    let crate_items: Vec<&IndexItem> = search_index
+        .iter_mut()
+        .map(|item| {
+            item.parent_idx = item.parent.and_then(|defid| match defid_to_pathid.entry(defid) {
+                Entry::Occupied(entry) => Some(*entry.get()),
+                Entry::Vacant(entry) => {
+                    let pathid = lastpathid;
+                    entry.insert(pathid);
+                    lastpathid += 1;
 
-                if let Some(&(ref fqp, short)) = paths.get(&defid) {
-                    crate_paths.push((short, fqp.last().unwrap().clone()));
-                    Some(pathid)
-                } else {
-                    None
+                    if let Some(&(ref fqp, short)) = paths.get(&defid) {
+                        crate_paths.push((short, fqp.last().unwrap().clone()));
+                        Some(pathid)
+                    } else {
+                        None
+                    }
                 }
+            });
+
+            // Omit the parent path if it is same to that of the prior item.
+            if lastpath == &item.path {
+                item.path.clear();
+            } else {
+                lastpath = &item.path;
             }
-        });
 
-        // Omit the parent path if it is same to that of the prior item.
-        if lastpath == item.path {
-            item.path.clear();
-        } else {
-            lastpath = item.path.clone();
-        }
-        crate_items.push(&*item);
-    }
+            &*item
+        })
+        .collect();
 
     struct CrateData<'a> {
         doc: String,
@@ -241,8 +244,10 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
 /// The point of this function is to replace bounds with types.
 ///
 /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
-/// `[Display, Option]` (we just returns the list of the types, we don't care about the
-/// wrapped types in here).
+/// `[Display, Option]`. If a type parameter has no trait bound, it is discarded.
+///
+/// Important note: It goes through generics recursively. So if you have
+/// `T: Option<Result<(), ()>>`, it'll go into `Option` and then into `Result`.
 crate fn get_real_types<'tcx>(
     generics: &Generics,
     arg: &Type,
@@ -258,45 +263,52 @@ fn insert_ty(
     ) {
         let is_full_generic = ty.is_full_generic();
 
-        if is_full_generic && generics.len() == 1 {
-            // In this case, no need to go through an intermediate state if the generics
-            // contains only one element.
-            //
-            // For example:
-            //
-            // fn foo<T: Display>(r: Option<T>) {}
-            //
-            // In this case, it would contain:
-            //
-            // ```
-            // [{
-            //     name: "option",
-            //     generics: [{
-            //         name: "",
-            //         generics: [
-            //             name: "Display",
-            //             generics: []
-            //         }]
-            //     }]
-            // }]
-            // ```
-            //
-            // After removing the intermediate (unnecessary) full generic, it'll become:
-            //
-            // ```
-            // [{
-            //     name: "option",
-            //     generics: [{
-            //         name: "Display",
-            //         generics: []
-            //     }]
-            // }]
-            // ```
-            //
-            // To be noted that it can work if there is ONLY ONE generic, otherwise we still
-            // need to keep it as is!
-            res.push(generics.pop().unwrap());
-            return;
+        if is_full_generic {
+            if generics.is_empty() {
+                // This is a type parameter with no trait bounds (for example: `T` in
+                // `fn f<T>(p: T)`, so not useful for the rustdoc search because we would end up
+                // with an empty type with an empty name. Let's just discard it.
+                return;
+            } else if generics.len() == 1 {
+                // In this case, no need to go through an intermediate state if the type parameter
+                // contains only one trait bound.
+                //
+                // For example:
+                //
+                // `fn foo<T: Display>(r: Option<T>) {}`
+                //
+                // In this case, it would contain:
+                //
+                // ```
+                // [{
+                //     name: "option",
+                //     generics: [{
+                //         name: "",
+                //         generics: [
+                //             name: "Display",
+                //             generics: []
+                //         }]
+                //     }]
+                // }]
+                // ```
+                //
+                // After removing the intermediate (unnecessary) type parameter, it'll become:
+                //
+                // ```
+                // [{
+                //     name: "option",
+                //     generics: [{
+                //         name: "Display",
+                //         generics: []
+                //     }]
+                // }]
+                // ```
+                //
+                // To be noted that it can work if there is ONLY ONE trait bound, otherwise we still
+                // need to keep it as is!
+                res.push(generics.pop().unwrap());
+                return;
+            }
         }
         let mut index_ty = get_index_type(&ty, generics);
         if index_ty.name.as_ref().map(|s| s.is_empty()).unwrap_or(true) {
@@ -319,7 +331,10 @@ fn insert_ty(
         return;
     }
 
+    // If this argument is a type parameter and not a trait bound or a type, we need to look
+    // for its bounds.
     if let Type::Generic(arg_s) = *arg {
+        // First we check if the bounds are in a `where` predicate...
         if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g {
             WherePredicate::BoundPredicate { ty, .. } => {
                 ty.def_id_no_primitives() == arg.def_id_no_primitives()
@@ -342,6 +357,7 @@ fn insert_ty(
             }
             insert_ty(res, tcx, arg.clone(), ty_generics);
         }
+        // Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
         if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
             let mut ty_generics = Vec::new();
             for bound in bound.get_bounds().unwrap_or(&[]) {
@@ -353,6 +369,11 @@ fn insert_ty(
             insert_ty(res, tcx, arg.clone(), ty_generics);
         }
     } else {
+        // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
+        // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
+        //
+        // So in here, we can add it directly and look for its own type parameters (so for `Option`,
+        // we will look for them but not for `T`).
         let mut ty_generics = Vec::new();
         if let Some(arg_generics) = arg.generics() {
             for gen in arg_generics.iter() {
index 25fef114d95fd8bc67cb857ff9f3670856a4f41d..fdadc68998dc663f98609c190841b75d3f09f5f8 100644 (file)
@@ -34,8 +34,8 @@
 mod templates;
 mod write_shared;
 
-crate use context::*;
-crate use span_map::{collect_spans_and_sources, LinkFromSrc};
+crate use self::context::*;
+crate use self::span_map::{collect_spans_and_sources, LinkFromSrc};
 
 use std::collections::VecDeque;
 use std::default::Default;
@@ -54,6 +54,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::Mutability;
 use rustc_middle::middle::stability;
+use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::{
     symbol::{kw, sym, Symbol},
@@ -1147,9 +1148,9 @@ fn render_assoc_items_inner(
         }
 
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
-            traits.iter().partition(|t| t.inner_impl().synthetic);
+            traits.iter().partition(|t| t.inner_impl().kind.is_auto());
         let (blanket_impl, concrete): (Vec<&&Impl>, _) =
-            concrete.into_iter().partition(|t| t.inner_impl().blanket_impl.is_some());
+            concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
 
         let mut impls = Buffer::empty_from(w);
         render_impls(cx, &mut impls, &concrete, containing_item);
@@ -2033,12 +2034,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
                             let i_display = format!("{:#}", i.print(cx));
                             let out = Escape(&i_display);
                             let encoded = small_url_encode(format!("{:#}", i.print(cx)));
-                            let generated = format!(
-                                "<a href=\"#impl-{}\">{}{}</a>",
-                                encoded,
-                                if it.inner_impl().negative_polarity { "!" } else { "" },
-                                out
-                            );
+                            let prefix = match it.inner_impl().polarity {
+                                ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
+                                ty::ImplPolarity::Negative => "!",
+                            };
+                            let generated =
+                                format!("<a href=\"#impl-{}\">{}{}</a>", encoded, prefix, out);
                             if links.insert(generated.clone()) { Some(generated) } else { None }
                         } else {
                             None
@@ -2058,10 +2059,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             };
 
             let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
-                v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().synthetic);
-            let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete
-                .into_iter()
-                .partition::<Vec<_>, _>(|i| i.inner_impl().blanket_impl.is_some());
+                v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
+            let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
+                concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
 
             let concrete_format = format_impls(concrete);
             let synthetic_format = format_impls(synthetic);
index d07ef6db4c6b0127e230d267e2d9e2f06be85bcd..7ef773fe5ff29dde2338ef963426cb4d5b2b419f 100644 (file)
@@ -746,7 +746,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         });
 
         let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
-            local.iter().partition(|i| i.inner_impl().synthetic);
+            local.iter().partition(|i| i.inner_impl().kind.is_auto());
 
         synthetic.sort_by(|a, b| compare_impl(a, b, cx));
         concrete.sort_by(|a, b| compare_impl(a, b, cx));
index 978701746b75b135acde7172be31087d7e1c4fc9..2d3b2490677e9b3e029cbad752a3a58368f6a965 100644 (file)
@@ -585,7 +585,7 @@ struct Implementor {
                 } else {
                     Some(Implementor {
                         text: imp.inner_impl().print(false, cx).to_string(),
-                        synthetic: imp.inner_impl().synthetic,
+                        synthetic: imp.inner_impl().kind.is_auto(),
                         types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache),
                     })
                 }
index f740ecdbded74a9a2ed9cdfe01ca99f2f6b5fce4..a46518ef489aa1b3bc1a53d38ad358800826b1ce 100644 (file)
@@ -9,7 +9,7 @@
 
 use rustc_ast::ast;
 use rustc_hir::{def::CtorKind, def_id::DefId};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::CRATE_DEF_INDEX;
 use rustc_span::Pos;
 
@@ -500,22 +500,22 @@ fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self {
 impl FromWithTcx<clean::Impl> for Impl {
     fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
         let provided_trait_methods = impl_.provided_trait_methods(tcx);
-        let clean::Impl {
-            unsafety,
-            generics,
-            trait_,
-            for_,
-            items,
-            negative_polarity,
-            synthetic,
-            blanket_impl,
-            span: _span,
-        } = impl_;
+        let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
         // FIXME: should `trait_` be a clean::Path equivalent in JSON?
         let trait_ = trait_.map(|path| {
             let did = path.def_id();
             clean::ResolvedPath { path, did }.into_tcx(tcx)
         });
+        // FIXME: use something like ImplKind in JSON?
+        let (synthetic, blanket_impl) = match kind {
+            clean::ImplKind::Normal => (false, None),
+            clean::ImplKind::Auto => (true, None),
+            clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
+        };
+        let negative_polarity = match polarity {
+            ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
+            ty::ImplPolarity::Negative => true,
+        };
         Impl {
             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
             generics: generics.into_tcx(tcx),
@@ -528,7 +528,7 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
             items: ids(items),
             negative: negative_polarity,
             synthetic,
-            blanket_impl: blanket_impl.map(|x| (*x).into_tcx(tcx)),
+            blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
         }
     }
 }
index 7eeb9d1fcaa55114b3b08c06320aa8345dd0e5fd..1c12cc547e0da1a64b52755ccc07fbc49031da11 100644 (file)
@@ -9,6 +9,7 @@
 #![feature(control_flow_enum)]
 #![feature(box_syntax)]
 #![feature(in_band_lifetimes)]
+#![feature(let_else)]
 #![feature(nll)]
 #![feature(test)]
 #![feature(crate_visibility_modifier)]
@@ -755,6 +756,7 @@ fn main_options(options: config::Options) -> MainResult {
     let default_passes = options.default_passes;
     let output_format = options.output_format;
     // FIXME: fix this clone (especially render_options)
+    let externs = options.externs.clone();
     let manual_passes = options.manual_passes.clone();
     let render_options = options.render_options.clone();
     let scrape_examples_options = options.scrape_examples_options.clone();
@@ -773,9 +775,9 @@ fn main_options(options: config::Options) -> MainResult {
             // We need to hold on to the complete resolver, so we cause everything to be
             // cloned for the analysis passes to use. Suboptimal, but necessary in the
             // current architecture.
-            let resolver = core::create_resolver(queries, sess);
+            let resolver = core::create_resolver(externs, queries, sess);
 
-            if sess.has_errors() {
+            if sess.diagnostic().has_errors_or_lint_errors() {
                 sess.fatal("Compilation failed, aborting rustdoc");
             }
 
index 8541e6e18816f5c783800fbe23be99e5780cc1fc..4e5812d7f8429e38a5a5f11042f5912b0a5ee0a4 100644 (file)
@@ -1937,7 +1937,8 @@ fn split(path: &str) -> Option<(&str, &str)> {
                             | Use
                             | LifetimeParam
                             | Ctor(_, _)
-                            | AnonConst => {
+                            | AnonConst
+                            | InlineConst => {
                                 let note = assoc_item_not_allowed(res);
                                 if let Some(span) = sp {
                                     diag.span_label(span, &note);
index 565bcb8bd1340c4763a24c33a800894f3c9f5f9a..4cebf741e200271ce837e047fd81cc587c673e4b 100644 (file)
@@ -1,3 +1,4 @@
+use ast::visit;
 use rustc_ast as ast;
 use rustc_hir::def::Namespace::TypeNS;
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@@ -16,7 +17,7 @@
     let mut loader = IntraLinkCrateLoader { current_mod: CRATE_DEF_ID, resolver };
     // `walk_crate` doesn't visit the crate itself for some reason.
     loader.load_links_in_attrs(&krate.attrs, krate.span);
-    ast::visit::walk_crate(&mut loader, krate);
+    visit::walk_crate(&mut loader, krate);
     loader.resolver
 }
 
@@ -54,7 +55,12 @@ fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute], span: Span) {
     }
 }
 
-impl ast::visit::Visitor<'_> for IntraLinkCrateLoader {
+impl visit::Visitor<'_> for IntraLinkCrateLoader {
+    fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
+        self.load_links_in_attrs(&item.attrs, item.span);
+        visit::walk_foreign_item(self, item)
+    }
+
     fn visit_item(&mut self, item: &ast::Item) {
         use rustc_ast_lowering::ResolverAstLowering;
 
@@ -64,12 +70,29 @@ fn visit_item(&mut self, item: &ast::Item) {
             let old_mod = mem::replace(&mut self.current_mod, new_mod);
 
             self.load_links_in_attrs(&item.attrs, item.span);
-            ast::visit::walk_item(self, item);
+            visit::walk_item(self, item);
 
             self.current_mod = old_mod;
         } else {
             self.load_links_in_attrs(&item.attrs, item.span);
-            ast::visit::walk_item(self, item);
+            visit::walk_item(self, item);
         }
     }
+
+    // NOTE: if doc-comments are ever allowed on function parameters, this will have to implement `visit_param` too.
+
+    fn visit_assoc_item(&mut self, item: &ast::AssocItem, ctxt: visit::AssocCtxt) {
+        self.load_links_in_attrs(&item.attrs, item.span);
+        visit::walk_assoc_item(self, item, ctxt)
+    }
+
+    fn visit_field_def(&mut self, field: &ast::FieldDef) {
+        self.load_links_in_attrs(&field.attrs, field.span);
+        visit::walk_field_def(self, field)
+    }
+
+    fn visit_variant(&mut self, v: &ast::Variant) {
+        self.load_links_in_attrs(&v.attrs, v.span);
+        visit::walk_variant(self, v)
+    }
 }
index 77513b05ff2f94ca982b0649291ce9aab8c46667..ea50134f00d477c485322b5ef9c0f423a4086d4c 100644 (file)
@@ -111,12 +111,12 @@ fn add_deref_target(
     }
 
     new_items.retain(|it| {
-        if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
+        if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
             cleaner.keep_impl(
                 for_,
                 trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(),
             ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into()))
-                || blanket_impl.is_some()
+                || kind.is_blanket()
         } else {
             true
         }
index 1b5a750455248610ae2295adf7a0d33d7e23e343..3b39e3576e69a39d22f577b29dd3ab4c173feebf 100644 (file)
@@ -48,7 +48,7 @@ impl ScrapeExamplesOptions {
                 target_crates,
             })),
             (Some(_), false) | (None, true) => {
-                diag.err(&format!("must use --scrape-examples-output-path and --scrape-examples-target-crate together"));
+                diag.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
                 Err(1)
             }
             (None, false) => Ok(None),
index 5d1f934240f037f0de0e2c18e8252a543f350957..1191a94a7039bee6bf544d7d182dc31e706867c9 100644 (file)
@@ -10,7 +10,6 @@
 use rustc_middle::middle::privacy::AccessLevel;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 
 use std::mem;
@@ -72,9 +71,7 @@ fn store_path(&mut self, did: DefId) {
     }
 
     crate fn visit(mut self) -> Module<'tcx> {
-        let span = self.cx.tcx.def_span(CRATE_DEF_ID);
         let mut top_level_module = self.visit_mod_contents(
-            &Spanned { span, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
             self.cx.tcx.hir().root_module(),
             self.cx.tcx.crate_name(LOCAL_CRATE),
@@ -134,15 +131,15 @@ fn store_path(&mut self, did: DefId) {
 
     fn visit_mod_contents(
         &mut self,
-        vis: &hir::Visibility<'_>,
         id: hir::HirId,
         m: &'tcx hir::Mod<'tcx>,
         name: Symbol,
     ) -> Module<'tcx> {
         let mut om = Module::new(name, id, m.inner);
+        let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
-        self.inside_public_path &= vis.node.is_pub();
+        self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
             self.visit_item(item, None, &mut om);
@@ -259,7 +256,7 @@ fn visit_item(
         let name = renamed.unwrap_or(item.ident.name);
 
         let def_id = item.def_id.to_def_id();
-        let is_pub = item.vis.node.is_pub() || self.cx.tcx.has_attr(def_id, sym::macro_export);
+        let is_pub = self.cx.tcx.visibility(def_id).is_public();
 
         if is_pub {
             self.store_path(item.def_id.to_def_id());
@@ -332,7 +329,7 @@ fn visit_item(
                 }
             }
             hir::ItemKind::Mod(ref m) => {
-                om.mods.push(self.visit_mod_contents(&item.vis, item.hir_id(), m, name));
+                om.mods.push(self.visit_mod_contents(item.hir_id(), m, name));
             }
             hir::ItemKind::Fn(..)
             | hir::ItemKind::ExternCrate(..)
@@ -368,7 +365,7 @@ fn visit_foreign_item(
         om: &mut Module<'tcx>,
     ) {
         // If inlining we only want to include public functions.
-        if !self.inlining || item.vis.node.is_pub() {
+        if !self.inlining || self.cx.tcx.visibility(item.def_id).is_public() {
             om.foreigns.push((item, renamed));
         }
     }
index 3e98ba08fb9ca376dbb5b4e4b0d307811f909e6d..791f7ff437c8bf4e86229cbb7831cdc0abd5407b 100644 (file)
@@ -2,7 +2,7 @@
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
-use rustc_middle::ty::{TyCtxt, Visibility};
+use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
 use crate::clean::{AttributesExt, NestedAttributesExt};
@@ -59,7 +59,7 @@ fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLev
         for item in self.tcx.item_children(def_id).iter() {
             if let Some(def_id) = item.res.opt_def_id() {
                 if self.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index)
-                    || item.vis == Visibility::Public
+                    || item.vis.is_public()
                 {
                     self.visit_item(item.res);
                 }
@@ -70,7 +70,7 @@ fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLev
     fn visit_item(&mut self, res: Res<!>) {
         let def_id = res.def_id();
         let vis = self.tcx.visibility(def_id);
-        let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None };
+        let inherited_item_level = if vis.is_public() { self.prev_level } else { None };
 
         let item_level = self.update(def_id, inherited_item_level);
 
index a7348ae0df3c71581dbe3d355fc0fb6ce6332dd0..e048e97f5280e8a232a43ae134d395aeab67c2e8 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a7348ae0df3c71581dbe3d355fc0fb6ce6332dd0
+Subproject commit e048e97f5280e8a232a43ae134d395aeab67c2e8
index 66c39a48c6e1d5fbc1ecb2ea3207c5dedeb4af37..04b5f4aed9bb5c87ef34b0658a78c60586022d39 100644 (file)
@@ -2,7 +2,7 @@
 // compile-flags: --target aarch64-unknown-linux-gnu
 // needs-llvm-components: aarch64
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index c848e3284ff1f06bb1926b6ba7587e13b2bb5983..0c57b1fc4782de50a8752cb372d439e973ea18b9 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: -C target-feature=+neon
 // needs-llvm-components: arm
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index 7271ef11287efcfd8c6614ffd25291adc5fb7045..3428d93fb1205d60b3e3040a76996cbbc4552c08 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
 // needs-llvm-components: bpf
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index 1c981040d601474da4547213aa610003c4e16e0d..7e48c386abcde7cc978b0e5ef4653413e00a8601 100644 (file)
@@ -2,7 +2,7 @@
 // assembly-output: emit-asm
 // compile-flags: -C llvm-args=--x86-asm-syntax=intel
 
-#![feature(asm, global_asm)]
+#![feature(global_asm, asm_const)]
 #![crate_type = "rlib"]
 
 // CHECK: mov eax, eax
index 2156d77233d83888f99ed4ee9454596dfb4920e2..de310c78488d9e9fea925fb0f32644c61898cefc 100644 (file)
@@ -2,7 +2,7 @@
 // compile-flags: --target hexagon-unknown-linux-musl
 // needs-llvm-components: hexagon
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index eb6627639f159d5d77a02c6e9756b7cdcffa5204..04bf49a40efbcd0b816754138a36717b5e64b6f3 100644 (file)
@@ -5,7 +5,7 @@
 //[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
 //[mips64] needs-llvm-components: mips
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index cc816fd78f81e2063c66a74e2740afe941b2182f..3ebd5b4b89681252dd4bc3715a03a55b408e7d02 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: --crate-type cdylib
 // needs-llvm-components: nvptx
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
 #![no_core]
 
 #[rustc_builtin_macro]
index 342998245315e8be0eeb55ce1bfb4c235b218d3b..b8859c07e164fe03a38ba7654802920bf488f6bc 100644 (file)
@@ -6,7 +6,7 @@
 //[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
 //[powerpc64] needs-llvm-components: powerpc
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index c510689b42bff788ce2ac9626c10a10446eabf08..0f9f61bd6d916a85d4bd7c5aa908574949e2aaa1 100644 (file)
@@ -6,7 +6,7 @@
 //[riscv32] needs-llvm-components: riscv
 // compile-flags: -C target-feature=+d
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register)]
index b8a4ca08df1cc8ce2d06a39ad7513558b69ede8c..6a12902a0461f711d76f08bdfb70428b37c53c95 100644 (file)
@@ -3,7 +3,7 @@
 //[s390x] compile-flags: --target s390x-unknown-linux-gnu
 //[s390x] needs-llvm-components: systemz
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
index 4b2e83e69b1065ba5701286557cbcbc373176632..3aa128c46ac01f8e6ef8e824a0f5fd66ff88674b 100644 (file)
@@ -3,7 +3,7 @@
 // compile-flags: --crate-type cdylib
 // needs-llvm-components: webassembly
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
 #![no_core]
 
 #[rustc_builtin_macro]
index 81be79cbaac18c25d8e9516bd8bb6327bdb6b92d..e871535cfdeef75a79da05884a06faa1b4c911cd 100644 (file)
@@ -7,7 +7,7 @@
 // compile-flags: -C llvm-args=--x86-asm-syntax=intel
 // compile-flags: -C target-feature=+avx512bw
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/codegen/array-clone.rs b/src/test/codegen/array-clone.rs
new file mode 100644 (file)
index 0000000..0d42963
--- /dev/null
@@ -0,0 +1,15 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @array_clone
+#[no_mangle]
+pub fn array_clone(a: &[u8; 2]) -> [u8; 2] {
+    // CHECK-NOT: getelementptr
+    // CHECK-NOT: load i8
+    // CHECK-NOT: zext
+    // CHECK-NOT: shl
+    // CHECK: load i16
+    // CHECK-NEXT: ret i16
+    a.clone()
+}
index ce13a7ff938c8beb23ce18f7c230dd6ddfc4f8aa..10b20ba6beb0a614cdb53a13ceed46fc8fa97978 100644 (file)
@@ -7,7 +7,7 @@
 //[powerpc64le] needs-llvm-components: powerpc
 
 #![crate_type = "rlib"]
-#![feature(no_core, rustc_attrs, lang_items)]
+#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
 #![no_core]
 
 #[lang = "sized"]
index 906d094f72b4a1b45b838babfc42698c8a3e67de..39f665402b025cf12918fba727f95bc93ecf6410 100644 (file)
@@ -1,4 +1,4 @@
-// EMIT_MIR issue_78192.f.InstCombine.diff
+// compile-flags: -Zmir-opt-level=1 -Zinline-mir
 pub fn f<T>(a: &T) -> *const T {
     let b: &*const T = &(a as *const T);
     *b
@@ -7,3 +7,5 @@ pub fn f<T>(a: &T) -> *const T {
 fn main() {
     f(&2);
 }
+
+// EMIT_MIR issue_78192.f.InstCombine.diff
index f4be3c1c63a84e5d8fda7b09ff7cf076ed3bebe6..84eda08d203bfcacfe288766a7c38bc13888e9ef 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     {
         ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"],
                                                          &match () {
-                                                              () => [],
+                                                              _args => [],
                                                           }));
     };
 }
index 199aee05622beed636c3966d6a00f091fae86cdd..529daab903887de6122e0cbb8eb4b0cb096d0f5b 100644 (file)
@@ -45,7 +45,7 @@ pub fn bar() ({
                                                                                                                                                                      as
                                                                                                                                                                      ())
                                                                                                                                                                {
-                                                                                                                                                               ()
+                                                                                                                                                               _args
                                                                                                                                                                =>
                                                                                                                                                                ([]
                                                                                                                                                                    as
index c75713c3ee53d1798915a4abfd36c4144a0669ec..de463a330149b0416afbf5b98c21a4591082a5da 100644 (file)
@@ -3,4 +3,4 @@
 all:
        touch $(TMPDIR)/lib.rmeta
        $(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/lib.rmeta
-       $(RUSTC) foo.rs 2>&1 | $(CGREP) "can't find crate for"
+       $(RUSTC) foo.rs 2>&1 | $(CGREP) "found invalid metadata"
index 013bf3baca45f1d18d321ba80ea4641bbc72ecbc..5472baae3f2b0bb0d1a9de1cef1b0bf7729524ba 100644 (file)
@@ -1,3 +1,5 @@
+# needs-llvm-components: x86 arm
+
 -include ../tools.mk
 
 all: default
diff --git a/src/test/run-make/invalid-so/Makefile b/src/test/run-make/invalid-so/Makefile
new file mode 100644 (file)
index 0000000..5b82ecd
--- /dev/null
@@ -0,0 +1,7 @@
+include ../../run-make-fulldeps/tools.mk
+
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -)
+
+all:
+       echo >> $(TMPDIR)/$(DYLIB_NAME)
+       $(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`'
diff --git a/src/test/run-make/invalid-so/bar.rs b/src/test/run-make/invalid-so/bar.rs
new file mode 100644 (file)
index 0000000..49af74e
--- /dev/null
@@ -0,0 +1 @@
+extern crate foo;
diff --git a/src/test/run-make/issue-10971-temps-dir/Makefile b/src/test/run-make/issue-10971-temps-dir/Makefile
new file mode 100644 (file)
index 0000000..5ce2719
--- /dev/null
@@ -0,0 +1,10 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# Regression test for issue #10971
+# Running two invocations in parallel would overwrite each other's temp files.
+
+all:
+       touch $(TMPDIR)/lib.rs
+
+       $(RUSTC) --crate-type=lib -Z temps-dir=$(TMPDIR)/temp1 $(TMPDIR)/lib.rs & \
+       $(RUSTC) --crate-type=staticlib -Z temps-dir=$(TMPDIR)/temp2 $(TMPDIR)/lib.rs
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs
new file mode 100644 (file)
index 0000000..d11c69f
--- /dev/null
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs
new file mode 100644 (file)
index 0000000..d11c69f
--- /dev/null
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs
new file mode 100644 (file)
index 0000000..d11c69f
--- /dev/null
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs
new file mode 100644 (file)
index 0000000..d11c69f
--- /dev/null
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs b/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs
new file mode 100644 (file)
index 0000000..438c56a
--- /dev/null
@@ -0,0 +1,26 @@
+// check-pass
+// aux-crate:dep1=dep1.rs
+// aux-crate:dep2=dep2.rs
+// aux-crate:dep3=dep3.rs
+// aux-crate:dep4=dep4.rs
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub trait Trait {
+    /// [dep1]
+    type Item;
+}
+
+pub struct S {
+    /// [dep2]
+    pub x: usize,
+}
+
+extern "C" {
+    /// [dep3]
+    pub fn printf();
+}
+
+pub enum E {
+    /// [dep4]
+    A
+}
diff --git a/src/test/rustdoc/include_str_cut.rs b/src/test/rustdoc/include_str_cut.rs
new file mode 100644 (file)
index 0000000..cbc1ba8
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+#![no_std]
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="docblock"]' 'inc2 x'
+#[doc = include_str!("short-line.md")]
+pub fn foo() {}
diff --git a/src/test/rustdoc/short-line.md b/src/test/rustdoc/short-line.md
new file mode 100644 (file)
index 0000000..eff713b
--- /dev/null
@@ -0,0 +1,2 @@
+inc2
+x
index f92bcd213b844a272914c36cf2ceea10bb58ab0f..0d04eb6fcfa968be6ad6f942561531619a719bda 100644 (file)
 //~^ WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_lint` is deprecated and may not have an effect in the future
 #![deny(clippy_group)]
 //~^ WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `clippy_group` is deprecated and may not have an effect in the future
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
@@ -30,6 +32,7 @@ fn lintmetoo() { } //~ ERROR item is named 'lintmetoo'
 //~^ WARNING lint name `test_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 //~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
+//~| WARNING lint name `test_group` is deprecated and may not have an effect in the future
 #[deny(this_lint_does_not_exist)] //~ WARNING unknown lint: `this_lint_does_not_exist`
 fn hello() {
     fn lintmetoo() { }
index 2260477a91d39a642d9d83e053c76dbf9bf4c0b5..0f76384ed5ba5001d6325ea8407e1322a53e7222 100644 (file)
@@ -7,19 +7,19 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    = note: `#[warn(renamed_and_removed_lints)]` on by default
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
 warning: unknown lint: `this_lint_does_not_exist`
-  --> $DIR/lint-tool-test.rs:33:8
+  --> $DIR/lint-tool-test.rs:36:8
    |
 LL | #[deny(this_lint_does_not_exist)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,13 +33,13 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
@@ -59,42 +59,60 @@ LL | #![cfg_attr(foo, warn(test_lint))]
    |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
 
 warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
 
 error: item is named 'lintme'
-  --> $DIR/lint-tool-test.rs:18:1
+  --> $DIR/lint-tool-test.rs:20:1
    |
 LL | fn lintme() { }
    | ^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_lint)]` implied by `#[deny(clippy::group)]`
 
 error: item is named 'lintmetoo'
-  --> $DIR/lint-tool-test.rs:26:5
+  --> $DIR/lint-tool-test.rs:28:5
    |
 LL |     fn lintmetoo() { }
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/lint-tool-test.rs:13:9
+  --> $DIR/lint-tool-test.rs:14:9
    |
 LL | #![deny(clippy_group)]
    |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
-  --> $DIR/lint-tool-test.rs:29:9
+  --> $DIR/lint-tool-test.rs:31:9
    |
 LL | #[allow(test_group)]
    |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
 
-error: aborting due to 2 previous errors; 11 warnings emitted
+warning: lint name `test_lint` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:9:23
+   |
+LL | #![cfg_attr(foo, warn(test_lint))]
+   |                       ^^^^^^^^^ help: change it to: `clippy::test_lint`
+
+warning: lint name `clippy_group` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:14:9
+   |
+LL | #![deny(clippy_group)]
+   |         ^^^^^^^^^^^^ help: change it to: `clippy::group`
+
+warning: lint name `test_group` is deprecated and may not have an effect in the future.
+  --> $DIR/lint-tool-test.rs:31:9
+   |
+LL | #[allow(test_group)]
+   |         ^^^^^^^^^^ help: change it to: `clippy::test_group`
+
+error: aborting due to 2 previous errors; 14 warnings emitted
 
diff --git a/src/test/ui/argument-passing.rs b/src/test/ui/argument-passing.rs
deleted file mode 100644 (file)
index 74759a4..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// run-pass
-
-struct X {
-    x: isize
-}
-
-fn f1(a: &mut X, b: &mut isize, c: isize) -> isize {
-    let r = a.x + *b + c;
-    a.x = 0;
-    *b = 10;
-    return r;
-}
-
-fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; }
-
-pub fn main() {
-    let mut a = X {x: 1};
-    let mut b = 2;
-    let c = 3;
-    assert_eq!(f1(&mut a, &mut b, c), 6);
-    assert_eq!(a.x, 0);
-    assert_eq!(b, 10);
-    assert_eq!(f2(a.x, |_| a.x = 50), 0);
-    assert_eq!(a.x, 50);
-}
diff --git a/src/test/ui/array-slice-vec/mut-vstore-expr.rs b/src/test/ui/array-slice-vec/mut-vstore-expr.rs
new file mode 100644 (file)
index 0000000..75b309a
--- /dev/null
@@ -0,0 +1,6 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+    let _x: &mut [isize] = &mut [ 1, 2, 3 ];
+}
index 22d0499a1cc1d0c3cb6da58e8f82dd4d779cd385..4d7a7fd31feca7b5dacb21236ce712ffdbc20c6b 100644 (file)
@@ -1,7 +1,7 @@
 // only-aarch64
 // compile-flags: -C target-feature=+fp
 
-#![feature(asm)]
+#![feature(asm, asm_const, asm_sym)]
 
 fn main() {
     let mut foo = 0;
index 05165b2d46c0dd3eb85fccd5dd7711d57592b269..49fe48600c25c4948df632d25a2a02d82cb07338 100644 (file)
@@ -3,7 +3,7 @@
 // revisions: mirunsafeck thirunsafeck
 // [thirunsafeck]compile-flags: -Z thir-unsafeck
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn const_generic<const X: usize>() -> usize {
     unsafe {
index faa5e37b781ecffe1f8352304c112f472c1ce7b6..bc0aed8fe55b2e869b7d66bbdc1321a1f5b54a41 100644 (file)
@@ -1,6 +1,6 @@
 // only-aarch64
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn main() {
     let mut foo = 0;
@@ -40,9 +40,9 @@ fn main() {
         asm!("", clobber_abi(foo));
         //~^ ERROR expected string literal
         asm!("", clobber_abi("C" foo));
-        //~^ ERROR expected `)`, found `foo`
+        //~^ ERROR expected one of `)` or `,`, found `foo`
         asm!("", clobber_abi("C", foo));
-        //~^ ERROR expected `)`, found `,`
+        //~^ ERROR expected string literal
         asm!("{}", clobber_abi("C"), const foo);
         //~^ ERROR arguments are not allowed after clobber_abi
         //~^^ ERROR attempt to use a non-constant value in a constant
@@ -50,8 +50,6 @@ fn main() {
         //~^ ERROR clobber_abi is not allowed after options
         asm!("{}", options(), clobber_abi("C"), const foo);
         //~^ ERROR clobber_abi is not allowed after options
-        asm!("", clobber_abi("C"), clobber_abi("C"));
-        //~^ ERROR clobber_abi specified multiple times
         asm!("{a}", a = const foo, a = const bar);
         //~^ ERROR duplicate argument named `a`
         //~^^ ERROR argument never used
@@ -110,9 +108,9 @@ fn main() {
 global_asm!("", clobber_abi(FOO));
 //~^ ERROR expected string literal
 global_asm!("", clobber_abi("C" FOO));
-//~^ ERROR expected `)`, found `FOO`
+//~^ ERROR expected one of `)` or `,`, found `FOO`
 global_asm!("", clobber_abi("C", FOO));
-//~^ ERROR expected `)`, found `,`
+//~^ ERROR expected string literal
 global_asm!("{}", clobber_abi("C"), const FOO);
 //~^ ERROR arguments are not allowed after clobber_abi
 //~^^ ERROR `clobber_abi` cannot be used with `global_asm!`
@@ -120,8 +118,6 @@ fn main() {
 //~^ ERROR clobber_abi is not allowed after options
 global_asm!("{}", options(), clobber_abi("C"), const FOO);
 //~^ ERROR clobber_abi is not allowed after options
-global_asm!("", clobber_abi("C"), clobber_abi("C"));
-//~^ ERROR clobber_abi specified multiple times
 global_asm!("{a}", a = const FOO, a = const BAR);
 //~^ ERROR duplicate argument named `a`
 //~^^ ERROR argument never used
index 6f318c9b9c2a172e654dc6827179a3d580143296..3d88cef5c7d71771c022f20c0b68a3915f354159 100644 (file)
@@ -96,17 +96,17 @@ error: expected string literal
 LL |         asm!("", clobber_abi(foo));
    |                              ^^^ not a string literal
 
-error: expected `)`, found `foo`
+error: expected one of `)` or `,`, found `foo`
   --> $DIR/parse-error.rs:42:34
    |
 LL |         asm!("", clobber_abi("C" foo));
-   |                                  ^^^ expected `)`
+   |                                  ^^^ expected one of `)` or `,`
 
-error: expected `)`, found `,`
-  --> $DIR/parse-error.rs:44:33
+error: expected string literal
+  --> $DIR/parse-error.rs:44:35
    |
 LL |         asm!("", clobber_abi("C", foo));
-   |                                 ^ expected `)`
+   |                                   ^^^ not a string literal
 
 error: arguments are not allowed after clobber_abi
   --> $DIR/parse-error.rs:46:38
@@ -132,16 +132,8 @@ LL |         asm!("{}", options(), clobber_abi("C"), const foo);
    |                    |
    |                    options
 
-error: clobber_abi specified multiple times
-  --> $DIR/parse-error.rs:53:36
-   |
-LL |         asm!("", clobber_abi("C"), clobber_abi("C"));
-   |                  ----------------  ^^^^^^^^^^^^^^^^
-   |                  |
-   |                  clobber_abi previously specified here
-
 error: duplicate argument named `a`
-  --> $DIR/parse-error.rs:55:36
+  --> $DIR/parse-error.rs:53:36
    |
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                     -------------  ^^^^^^^^^^^^^ duplicate argument
@@ -149,7 +141,7 @@ LL |         asm!("{a}", a = const foo, a = const bar);
    |                     previously here
 
 error: argument never used
-  --> $DIR/parse-error.rs:55:36
+  --> $DIR/parse-error.rs:53:36
    |
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                                    ^^^^^^^^^^^^^ argument never used
@@ -157,13 +149,13 @@ LL |         asm!("{a}", a = const foo, a = const bar);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
 error: explicit register arguments cannot have names
-  --> $DIR/parse-error.rs:60:18
+  --> $DIR/parse-error.rs:58:18
    |
 LL |         asm!("", a = in("x0") foo);
    |                  ^^^^^^^^^^^^^^^^
 
 error: named arguments cannot follow explicit register arguments
-  --> $DIR/parse-error.rs:62:35
+  --> $DIR/parse-error.rs:60:35
    |
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                     ------------  ^^^^^^^^^^^^^ named argument
@@ -171,7 +163,7 @@ LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                     explicit register argument
 
 error: named arguments cannot follow explicit register arguments
-  --> $DIR/parse-error.rs:65:35
+  --> $DIR/parse-error.rs:63:35
    |
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                     ------------  ^^^^^^^^^^^^^ named argument
@@ -179,7 +171,7 @@ LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                     explicit register argument
 
 error: positional arguments cannot follow named arguments or explicit register arguments
-  --> $DIR/parse-error.rs:68:35
+  --> $DIR/parse-error.rs:66:35
    |
 LL |         asm!("{1}", in("x0") foo, const bar);
    |                     ------------  ^^^^^^^^^ positional argument
@@ -187,19 +179,19 @@ LL |         asm!("{1}", in("x0") foo, const bar);
    |                     explicit register argument
 
 error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
-  --> $DIR/parse-error.rs:71:29
+  --> $DIR/parse-error.rs:69:29
    |
 LL |         asm!("", options(), "");
    |                             ^^ expected one of 9 possible tokens
 
 error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
-  --> $DIR/parse-error.rs:73:33
+  --> $DIR/parse-error.rs:71:33
    |
 LL |         asm!("{}", in(reg) foo, "{}", out(reg) foo);
    |                                 ^^^^ expected one of 9 possible tokens
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:75:14
+  --> $DIR/parse-error.rs:73:14
    |
 LL |         asm!(format!("{{{}}}", 0), in(reg) foo);
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -207,7 +199,7 @@ LL |         asm!(format!("{{{}}}", 0), in(reg) foo);
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:77:21
+  --> $DIR/parse-error.rs:75:21
    |
 LL |         asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
    |                     ^^^^^^^^^^^^^^^^^^^^
@@ -215,79 +207,79 @@ LL |         asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: _ cannot be used for input operands
-  --> $DIR/parse-error.rs:79:28
+  --> $DIR/parse-error.rs:77:28
    |
 LL |         asm!("{}", in(reg) _);
    |                            ^
 
 error: _ cannot be used for input operands
-  --> $DIR/parse-error.rs:81:31
+  --> $DIR/parse-error.rs:79:31
    |
 LL |         asm!("{}", inout(reg) _);
    |                               ^
 
 error: _ cannot be used for input operands
-  --> $DIR/parse-error.rs:83:35
+  --> $DIR/parse-error.rs:81:35
    |
 LL |         asm!("{}", inlateout(reg) _);
    |                                   ^
 
 error: requires at least a template string argument
-  --> $DIR/parse-error.rs:90:1
+  --> $DIR/parse-error.rs:88:1
    |
 LL | global_asm!();
    | ^^^^^^^^^^^^^
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:92:13
+  --> $DIR/parse-error.rs:90:13
    |
 LL | global_asm!(FOO);
    |             ^^^
 
 error: expected token: `,`
-  --> $DIR/parse-error.rs:94:18
+  --> $DIR/parse-error.rs:92:18
    |
 LL | global_asm!("{}" FOO);
    |                  ^^^ expected `,`
 
 error: expected operand, options, or additional template string
-  --> $DIR/parse-error.rs:96:19
+  --> $DIR/parse-error.rs:94:19
    |
 LL | global_asm!("{}", FOO);
    |                   ^^^ expected operand, options, or additional template string
 
 error: expected expression, found end of macro arguments
-  --> $DIR/parse-error.rs:98:24
+  --> $DIR/parse-error.rs:96:24
    |
 LL | global_asm!("{}", const);
    |                        ^ expected expression
 
 error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
-  --> $DIR/parse-error.rs:100:30
+  --> $DIR/parse-error.rs:98:30
    |
 LL | global_asm!("{}", const(reg) FOO);
    |                              ^^^ expected one of `,`, `.`, `?`, or an operator
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
-  --> $DIR/parse-error.rs:102:25
+  --> $DIR/parse-error.rs:100:25
    |
 LL | global_asm!("", options(FOO));
    |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/parse-error.rs:104:25
+  --> $DIR/parse-error.rs:102:25
    |
 LL | global_asm!("", options(nomem FOO));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/parse-error.rs:106:25
+  --> $DIR/parse-error.rs:104:25
    |
 LL | global_asm!("", options(nomem, FOO));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: arguments are not allowed after options
-  --> $DIR/parse-error.rs:108:30
+  --> $DIR/parse-error.rs:106:30
    |
 LL | global_asm!("{}", options(), const FOO);
    |                   ---------  ^^^^^^^^^ argument
@@ -295,25 +287,25 @@ LL | global_asm!("{}", options(), const FOO);
    |                   previous options
 
 error: expected string literal
-  --> $DIR/parse-error.rs:110:29
+  --> $DIR/parse-error.rs:108:29
    |
 LL | global_asm!("", clobber_abi(FOO));
    |                             ^^^ not a string literal
 
-error: expected `)`, found `FOO`
-  --> $DIR/parse-error.rs:112:33
+error: expected one of `)` or `,`, found `FOO`
+  --> $DIR/parse-error.rs:110:33
    |
 LL | global_asm!("", clobber_abi("C" FOO));
-   |                                 ^^^ expected `)`
+   |                                 ^^^ expected one of `)` or `,`
 
-error: expected `)`, found `,`
-  --> $DIR/parse-error.rs:114:32
+error: expected string literal
+  --> $DIR/parse-error.rs:112:34
    |
 LL | global_asm!("", clobber_abi("C", FOO));
-   |                                ^ expected `)`
+   |                                  ^^^ not a string literal
 
 error: arguments are not allowed after clobber_abi
-  --> $DIR/parse-error.rs:116:37
+  --> $DIR/parse-error.rs:114:37
    |
 LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   ----------------  ^^^^^^^^^ argument
@@ -321,13 +313,13 @@ LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   clobber_abi
 
 error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:116:19
+  --> $DIR/parse-error.rs:114:19
    |
 LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   ^^^^^^^^^^^^^^^^
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:119:28
+  --> $DIR/parse-error.rs:117:28
    |
 LL | global_asm!("", options(), clobber_abi("C"));
    |                 ---------  ^^^^^^^^^^^^^^^^
@@ -335,23 +327,15 @@ LL | global_asm!("", options(), clobber_abi("C"));
    |                 options
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:121:30
+  --> $DIR/parse-error.rs:119:30
    |
 LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
    |                   ---------  ^^^^^^^^^^^^^^^^
    |                   |
    |                   options
 
-error: clobber_abi specified multiple times
-  --> $DIR/parse-error.rs:123:35
-   |
-LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
-   |                 ----------------  ^^^^^^^^^^^^^^^^
-   |                 |
-   |                 clobber_abi previously specified here
-
 error: duplicate argument named `a`
-  --> $DIR/parse-error.rs:125:35
+  --> $DIR/parse-error.rs:121:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    -------------  ^^^^^^^^^^^^^ duplicate argument
@@ -359,7 +343,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    previously here
 
 error: argument never used
-  --> $DIR/parse-error.rs:125:35
+  --> $DIR/parse-error.rs:121:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                                   ^^^^^^^^^^^^^ argument never used
@@ -367,19 +351,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
 error: expected one of `clobber_abi`, `const`, or `options`, found `""`
-  --> $DIR/parse-error.rs:128:28
+  --> $DIR/parse-error.rs:124:28
    |
 LL | global_asm!("", options(), "");
    |                            ^^ expected one of `clobber_abi`, `const`, or `options`
 
 error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
-  --> $DIR/parse-error.rs:130:30
+  --> $DIR/parse-error.rs:126:30
    |
 LL | global_asm!("{}", const FOO, "{}", const FOO);
    |                              ^^^^ expected one of `clobber_abi`, `const`, or `options`
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:132:13
+  --> $DIR/parse-error.rs:128:13
    |
 LL | global_asm!(format!("{{{}}}", 0), const FOO);
    |             ^^^^^^^^^^^^^^^^^^^^
@@ -387,7 +371,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO);
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:134:20
+  --> $DIR/parse-error.rs:130:20
    |
 LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    |                    ^^^^^^^^^^^^^^^^^^^^
@@ -413,7 +397,7 @@ LL |         asm!("{}", clobber_abi("C"), const foo);
    |                                            ^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:55:31
+  --> $DIR/parse-error.rs:53:31
    |
 LL |     let mut foo = 0;
    |      ---------- help: consider using `const` instead of `let`: `const foo`
@@ -422,7 +406,7 @@ LL |         asm!("{a}", a = const foo, a = const bar);
    |                               ^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:55:46
+  --> $DIR/parse-error.rs:53:46
    |
 LL |     let mut bar = 0;
    |      ---------- help: consider using `const` instead of `let`: `const bar`
@@ -431,7 +415,7 @@ LL |         asm!("{a}", a = const foo, a = const bar);
    |                                              ^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:62:45
+  --> $DIR/parse-error.rs:60:45
    |
 LL |     let mut bar = 0;
    |      ---------- help: consider using `const` instead of `let`: `const bar`
@@ -440,7 +424,7 @@ LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:65:45
+  --> $DIR/parse-error.rs:63:45
    |
 LL |     let mut bar = 0;
    |      ---------- help: consider using `const` instead of `let`: `const bar`
@@ -449,7 +433,7 @@ LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:68:41
+  --> $DIR/parse-error.rs:66:41
    |
 LL |     let mut bar = 0;
    |      ---------- help: consider using `const` instead of `let`: `const bar`
@@ -457,6 +441,6 @@ LL |     let mut bar = 0;
 LL |         asm!("{1}", in("x0") foo, const bar);
    |                                         ^^^ non-constant value
 
-error: aborting due to 66 previous errors
+error: aborting due to 64 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
index 526555334cb882cd1cf2c5d97ef225bab56974fc..b0dd143a0a1b6de603dae63e6dfc7e7c8422a6dc 100644 (file)
@@ -2,7 +2,7 @@
 // only-linux
 // run-pass
 
-#![feature(asm, thread_local)]
+#![feature(asm, thread_local, asm_sym)]
 
 extern "C" fn f1() -> i32 {
     111
@@ -75,5 +75,7 @@ fn main() {
     std::thread::spawn(|| {
         assert_eq!(static_addr!(S1), &S1 as *const u32);
         assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
-    }).join().unwrap();
+    })
+    .join()
+    .unwrap();
 }
index cf25dcb930c7920e0c6cb2d185a75683094b2756..e1e8a91dda6033a8087682b4d5b2c5a65d730210 100644 (file)
@@ -1,6 +1,6 @@
 // only-aarch64
 
-#![feature(asm, repr_simd, never_type)]
+#![feature(asm, repr_simd, never_type, asm_sym)]
 
 #[repr(simd)]
 #[derive(Clone, Copy)]
index d0d5954ca4aef78eb67355cb1c9497743e024419..fc1831a520a0cbc0b702c7756cf5321d29231d75 100644 (file)
@@ -1,13 +1,13 @@
 // only-aarch64
 // compile-flags: -C target-feature=+neon
 
-#![feature(asm, global_asm, repr_simd, stdsimd)]
+#![feature(asm, global_asm, repr_simd, stdsimd, asm_const)]
 
 use std::arch::aarch64::float64x2_t;
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
-struct Simd256bit(f64, f64,f64, f64);
+struct Simd256bit(f64, f64, f64, f64);
 
 fn main() {
     let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) };
@@ -42,7 +42,6 @@ fn main() {
         asm!("{:b}", in(vreg) 0u64);
         asm!("{:d}", in(vreg_low16) f64x2);
 
-
         // Template modifier suggestions for sub-registers
 
         asm!("{}", in(reg) 0u8);
index c31a62ae7912a59e67303750374ae7f02520191f..ed9d3147b9ffaa52358a1fb85bd240bcb3a6e10d 100644 (file)
@@ -1,5 +1,5 @@
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:48:15
+  --> $DIR/type-check-3.rs:47:15
    |
 LL |         asm!("{}", in(reg) 0u8);
    |               ^^           --- for this argument
@@ -9,7 +9,7 @@ LL |         asm!("{}", in(reg) 0u8);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:50:15
+  --> $DIR/type-check-3.rs:49:15
    |
 LL |         asm!("{}", in(reg) 0u16);
    |               ^^           ---- for this argument
@@ -18,7 +18,7 @@ LL |         asm!("{}", in(reg) 0u16);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:52:15
+  --> $DIR/type-check-3.rs:51:15
    |
 LL |         asm!("{}", in(reg) 0i32);
    |               ^^           ---- for this argument
@@ -27,7 +27,7 @@ LL |         asm!("{}", in(reg) 0i32);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:54:15
+  --> $DIR/type-check-3.rs:53:15
    |
 LL |         asm!("{}", in(reg) 0f32);
    |               ^^           ---- for this argument
@@ -36,7 +36,7 @@ LL |         asm!("{}", in(reg) 0f32);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:57:15
+  --> $DIR/type-check-3.rs:56:15
    |
 LL |         asm!("{}", in(vreg) 0i16);
    |               ^^            ---- for this argument
@@ -45,7 +45,7 @@ LL |         asm!("{}", in(vreg) 0i16);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:59:15
+  --> $DIR/type-check-3.rs:58:15
    |
 LL |         asm!("{}", in(vreg) 0f32);
    |               ^^            ---- for this argument
@@ -54,7 +54,7 @@ LL |         asm!("{}", in(vreg) 0f32);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:61:15
+  --> $DIR/type-check-3.rs:60:15
    |
 LL |         asm!("{}", in(vreg) 0f64);
    |               ^^            ---- for this argument
@@ -63,7 +63,7 @@ LL |         asm!("{}", in(vreg) 0f64);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:63:15
+  --> $DIR/type-check-3.rs:62:15
    |
 LL |         asm!("{}", in(vreg_low16) 0f64);
    |               ^^                  ---- for this argument
@@ -72,7 +72,7 @@ LL |         asm!("{}", in(vreg_low16) 0f64);
    = help: or use the `v` modifier to keep the default formatting of `v0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:66:15
+  --> $DIR/type-check-3.rs:65:15
    |
 LL |         asm!("{0} {0}", in(reg) 0i16);
    |               ^^^ ^^^           ---- for this argument
@@ -81,7 +81,7 @@ LL |         asm!("{0} {0}", in(reg) 0i16);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 warning: formatting may not be suitable for sub-register argument
-  --> $DIR/type-check-3.rs:68:15
+  --> $DIR/type-check-3.rs:67:15
    |
 LL |         asm!("{0} {0:x}", in(reg) 0i16);
    |               ^^^                 ---- for this argument
@@ -90,7 +90,7 @@ LL |         asm!("{0} {0:x}", in(reg) 0i16);
    = help: or use the `x` modifier to keep the default formatting of `x0`
 
 error: type `i128` cannot be used with this register class
-  --> $DIR/type-check-3.rs:73:28
+  --> $DIR/type-check-3.rs:72:28
    |
 LL |         asm!("{}", in(reg) 0i128);
    |                            ^^^^^
@@ -98,7 +98,7 @@ LL |         asm!("{}", in(reg) 0i128);
    = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
 
 error: type `float64x2_t` cannot be used with this register class
-  --> $DIR/type-check-3.rs:75:28
+  --> $DIR/type-check-3.rs:74:28
    |
 LL |         asm!("{}", in(reg) f64x2);
    |                            ^^^^^
@@ -106,7 +106,7 @@ LL |         asm!("{}", in(reg) f64x2);
    = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
 
 error: type `Simd256bit` cannot be used with this register class
-  --> $DIR/type-check-3.rs:77:29
+  --> $DIR/type-check-3.rs:76:29
    |
 LL |         asm!("{}", in(vreg) f64x4);
    |                             ^^^^^
@@ -114,7 +114,7 @@ LL |         asm!("{}", in(vreg) f64x4);
    = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
 
 error: incompatible types for asm inout argument
-  --> $DIR/type-check-3.rs:88:33
+  --> $DIR/type-check-3.rs:87:33
    |
 LL |         asm!("{:x}", inout(reg) 0u32 => val_f32);
    |                                 ^^^^    ^^^^^^^ type `f32`
@@ -124,7 +124,7 @@ LL |         asm!("{:x}", inout(reg) 0u32 => val_f32);
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
 error: incompatible types for asm inout argument
-  --> $DIR/type-check-3.rs:90:33
+  --> $DIR/type-check-3.rs:89:33
    |
 LL |         asm!("{:x}", inout(reg) 0u32 => val_ptr);
    |                                 ^^^^    ^^^^^^^ type `*mut u8`
@@ -134,7 +134,7 @@ LL |         asm!("{:x}", inout(reg) 0u32 => val_ptr);
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
 error: incompatible types for asm inout argument
-  --> $DIR/type-check-3.rs:92:33
+  --> $DIR/type-check-3.rs:91:33
    |
 LL |         asm!("{:x}", inout(reg) main => val_u32);
    |                                 ^^^^    ^^^^^^^ type `u32`
@@ -144,7 +144,7 @@ LL |         asm!("{:x}", inout(reg) main => val_u32);
    = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
 
 error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:108:25
+  --> $DIR/type-check-3.rs:107:25
    |
 LL | global_asm!("{}", const S);
    |                         ^
@@ -152,7 +152,7 @@ LL | global_asm!("{}", const S);
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:111:35
+  --> $DIR/type-check-3.rs:110:35
    |
 LL | global_asm!("{}", const const_foo(S));
    |                                   ^
@@ -160,7 +160,7 @@ LL | global_asm!("{}", const const_foo(S));
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
 error[E0013]: constants cannot refer to statics
-  --> $DIR/type-check-3.rs:114:35
+  --> $DIR/type-check-3.rs:113:35
    |
 LL | global_asm!("{}", const const_bar(S));
    |                                   ^
index fca77e7aa71f37d9b3841cbaf4e9a1fe31793dd7..b062c45e6ea34947b37ab09c98d49f23f6a3eec2 100644 (file)
@@ -10,7 +10,7 @@
 // [aarch64_thirunsafeck] needs-llvm-components: aarch64
 // [aarch64_mirunsafeck] needs-llvm-components: aarch64
 
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_const)]
 #![no_core]
 
 #[rustc_builtin_macro]
index bdcf3f305ebb18cc6841ff79ad59cd70000c747c..a4b22e21028d90c52af9152915a4ccc56581469d 100644 (file)
@@ -2,6 +2,7 @@
 // as both unused and possibly-uninitialized.
 
 // check-pass
+// needs-asm-support
 
 #![feature(asm)]
 #![warn(unused)]
index 9cc127b44d008765b7a841efca42ab93d68f91f0..3fb1526183bccdbb3527ddc970947f44945398c9 100644 (file)
@@ -1,11 +1,11 @@
 warning: unused variable: `x`
-  --> $DIR/issue-89305.rs:11:13
+  --> $DIR/issue-89305.rs:12:13
    |
 LL |         let x: () = asm!("nop");
    |             ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
 note: the lint level is defined here
-  --> $DIR/issue-89305.rs:7:9
+  --> $DIR/issue-89305.rs:8:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
index 803311d4235058a0a6419f2c44a5a4f94b1692da..7154ce26efcf5e3833dec4a5ec96e69fdaa597e8 100644 (file)
@@ -7,11 +7,15 @@
 #![feature(llvm_asm)]
 #![feature(naked_functions)]
 #![feature(or_patterns)]
+#![feature(asm_const, asm_sym)]
 #![crate_type = "lib"]
 #![allow(deprecated)] // llvm_asm!
 
 #[repr(C)]
-pub struct P { x: u8, y: u16 }
+pub struct P {
+    x: u8,
+    y: u16,
+}
 
 #[naked]
 pub unsafe extern "C" fn patterns(
@@ -143,21 +147,27 @@ pub unsafe fn default_abi() {
 }
 
 #[naked]
-pub unsafe extern "Rust" fn rust_abi() {
+pub unsafe fn rust_abi() {
     //~^ WARN Rust ABI is unsupported in naked functions
     asm!("", options(noreturn));
 }
 
 #[naked]
 pub extern "C" fn valid_a<T>() -> T {
-    unsafe { asm!("", options(noreturn)); }
+    unsafe {
+        asm!("", options(noreturn));
+    }
 }
 
 #[naked]
 pub extern "C" fn valid_b() {
-    unsafe { { {
-        asm!("", options(noreturn)); ; ; ;
-    } ; }  ; }
+    unsafe {
+        {
+            {
+                asm!("", options(noreturn));
+            };
+        };
+    }
 }
 
 #[naked]
index 465db634aa2f0b84bf07c4a888150231d9521be6..e4ddb97ca27467393caa956ad8af2ab87031ea7b 100644 (file)
@@ -1,35 +1,35 @@
 error: asm with the `pure` option must have at least one output
-  --> $DIR/naked-functions.rs:131:14
+  --> $DIR/naked-functions.rs:135:14
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:18:5
+  --> $DIR/naked-functions.rs:22:5
    |
 LL |     mut a: u32,
    |     ^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:20:5
+  --> $DIR/naked-functions.rs:24:5
    |
 LL |     &b: &i32,
    |     ^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:22:6
+  --> $DIR/naked-functions.rs:26:6
    |
 LL |     (None | Some(_)): Option<std::ptr::NonNull<u8>>,
    |      ^^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:24:5
+  --> $DIR/naked-functions.rs:28:5
    |
 LL |     P { x, y }: P,
    |     ^^^^^^^^^^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:34:5
+  --> $DIR/naked-functions.rs:38:5
    |
 LL |     a + 1
    |     ^
@@ -37,7 +37,7 @@ LL |     a + 1
    = help: follow the calling convention in asm block to use parameters
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:31:1
+  --> $DIR/naked-functions.rs:35:1
    |
 LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
 LL | |
@@ -53,7 +53,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:40:31
+  --> $DIR/naked-functions.rs:44:31
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                               ^
@@ -61,7 +61,7 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = help: follow the calling convention in asm block to use parameters
 
 warning: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:40:23
+  --> $DIR/naked-functions.rs:44:23
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                       ^^^^^^^^^
@@ -70,7 +70,7 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:47:1
+  --> $DIR/naked-functions.rs:51:1
    |
 LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
 LL | |
@@ -84,7 +84,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:67:10
+  --> $DIR/naked-functions.rs:71:10
    |
 LL |          in(reg) a,
    |          ^^^^^^^^^
@@ -102,7 +102,7 @@ LL |          out(reg) e,
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:64:5
+  --> $DIR/naked-functions.rs:68:5
    |
 LL | /     asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
 LL | |
@@ -117,7 +117,7 @@ LL | |     );
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:54:1
+  --> $DIR/naked-functions.rs:58:1
    |
 LL | / pub unsafe extern "C" fn unsupported_operands() {
 LL | |
@@ -141,7 +141,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:80:1
+  --> $DIR/naked-functions.rs:84:1
    |
 LL | / pub extern "C" fn missing_assembly() {
 LL | |
@@ -153,7 +153,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:89:5
+  --> $DIR/naked-functions.rs:93:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -162,7 +162,7 @@ LL |     asm!("");
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:92:5
+  --> $DIR/naked-functions.rs:96:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -171,7 +171,7 @@ LL |     asm!("");
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:95:5
+  --> $DIR/naked-functions.rs:99:5
    |
 LL |     asm!("");
    |     ^^^^^^^^
@@ -180,7 +180,7 @@ LL |     asm!("");
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:86:1
+  --> $DIR/naked-functions.rs:90:1
    |
 LL | / pub extern "C" fn too_many_asm_blocks() {
 LL | |
@@ -202,7 +202,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:106:11
+  --> $DIR/naked-functions.rs:110:11
    |
 LL |         *&y
    |           ^
@@ -210,7 +210,7 @@ LL |         *&y
    = help: follow the calling convention in asm block to use parameters
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:103:5
+  --> $DIR/naked-functions.rs:107:5
    |
 LL | /     pub extern "C" fn inner(y: usize) -> usize {
 LL | |
@@ -225,7 +225,7 @@ LL | |     }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: the LLVM-style inline assembly is unsupported in naked functions
-  --> $DIR/naked-functions.rs:116:5
+  --> $DIR/naked-functions.rs:120:5
    |
 LL |     llvm_asm!("");
    |     ^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL |     llvm_asm!("");
    = note: this warning originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:113:1
+  --> $DIR/naked-functions.rs:117:1
    |
 LL | / unsafe extern "C" fn llvm() -> ! {
 LL | |
@@ -252,7 +252,7 @@ LL | | }
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
-  --> $DIR/naked-functions.rs:124:5
+  --> $DIR/naked-functions.rs:128:5
    |
 LL |     asm!("", options(nomem, preserves_flags, noreturn));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -261,7 +261,7 @@ LL |     asm!("", options(nomem, preserves_flags, noreturn));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
-  --> $DIR/naked-functions.rs:131:5
+  --> $DIR/naked-functions.rs:135:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -270,7 +270,7 @@ LL |     asm!("", options(readonly, nostack), options(pure));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:131:5
+  --> $DIR/naked-functions.rs:135:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -279,7 +279,7 @@ LL |     asm!("", options(readonly, nostack), options(pure));
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:140:15
+  --> $DIR/naked-functions.rs:144:15
    |
 LL | pub unsafe fn default_abi() {
    |               ^^^^^^^^^^^
@@ -287,13 +287,13 @@ LL | pub unsafe fn default_abi() {
    = note: `#[warn(undefined_naked_function_abi)]` on by default
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:146:29
+  --> $DIR/naked-functions.rs:150:15
    |
-LL | pub unsafe extern "Rust" fn rust_abi() {
-   |                             ^^^^^^^^
+LL | pub unsafe fn rust_abi() {
+   |               ^^^^^^^^
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:180:1
+  --> $DIR/naked-functions.rs:190:1
    |
 LL | #[inline]
    | ^^^^^^^^^
@@ -302,7 +302,7 @@ LL | #[inline]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:188:1
+  --> $DIR/naked-functions.rs:198:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
@@ -311,7 +311,7 @@ LL | #[inline(always)]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:196:1
+  --> $DIR/naked-functions.rs:206:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
@@ -320,7 +320,7 @@ LL | #[inline(never)]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:204:1
+  --> $DIR/naked-functions.rs:214:1
    |
 LL | #[inline]
    | ^^^^^^^^^
@@ -329,7 +329,7 @@ LL | #[inline]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:207:1
+  --> $DIR/naked-functions.rs:217:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
@@ -338,7 +338,7 @@ LL | #[inline(always)]
    = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
 
 warning: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:210:1
+  --> $DIR/naked-functions.rs:220:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
index 82c47945a7b302c4db11ee389e3c54877b98a46c..c87188e46a2bbedd92dcea45d37a764f86f14ba6 100644 (file)
@@ -11,7 +11,7 @@
 // which causes less readable LLVM errors and in the worst cases causes ICEs
 // or segfaults based on system dependent behavior and codegen flags.
 
-#![feature(asm, global_asm, naked_functions)]
+#![feature(asm, global_asm, naked_functions, asm_const)]
 
 #[no_mangle]
 pub static FOO: usize = 42;
index bbbe798d1557b0e095559ae2cff6fcfd19ebede2..1e463107b18bc4471f86e29aabe0ffbc360198f2 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-spirv
 // ignore-wasm32
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn main() {
     unsafe {
diff --git a/src/test/ui/asm/x86_64/bad-clobber-abi.rs b/src/test/ui/asm/x86_64/bad-clobber-abi.rs
new file mode 100644 (file)
index 0000000..f4ca033
--- /dev/null
@@ -0,0 +1,32 @@
+// needs-asm-support
+// only-x86_64
+
+// checks various modes of failure for the `clobber_abi` argument (after parsing)
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("", clobber_abi("C"));
+        asm!("", clobber_abi("foo"));
+        //~^ ERROR invalid ABI for `clobber_abi`
+        asm!("", clobber_abi("C", "foo"));
+        //~^ ERROR invalid ABI for `clobber_abi`
+        asm!("", clobber_abi("C", "C"));
+        //~^ ERROR `C` ABI specified multiple times
+        asm!("", clobber_abi("win64", "sysv64"));
+        asm!("", clobber_abi("win64", "efiapi"));
+        //~^ ERROR `win64` ABI specified multiple times
+        asm!("", clobber_abi("C", "foo", "C"));
+        //~^ ERROR invalid ABI for `clobber_abi`
+        //~| ERROR `C` ABI specified multiple times
+        asm!("", clobber_abi("win64", "foo", "efiapi"));
+        //~^ ERROR invalid ABI for `clobber_abi`
+        //~| ERROR `win64` ABI specified multiple times
+        asm!("", clobber_abi("C"), clobber_abi("C"));
+        //~^ ERROR `C` ABI specified multiple times
+        asm!("", clobber_abi("win64"), clobber_abi("sysv64"));
+        asm!("", clobber_abi("win64"), clobber_abi("efiapi"));
+        //~^ ERROR `win64` ABI specified multiple times
+    }
+}
diff --git a/src/test/ui/asm/x86_64/bad-clobber-abi.stderr b/src/test/ui/asm/x86_64/bad-clobber-abi.stderr
new file mode 100644 (file)
index 0000000..46e91a3
--- /dev/null
@@ -0,0 +1,88 @@
+error: invalid ABI for `clobber_abi`
+  --> $DIR/bad-clobber-abi.rs:11:18
+   |
+LL |         asm!("", clobber_abi("foo"));
+   |                  ^^^^^^^^^^^^^^^^^^
+   |
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: invalid ABI for `clobber_abi`
+  --> $DIR/bad-clobber-abi.rs:13:35
+   |
+LL |         asm!("", clobber_abi("C", "foo"));
+   |                                   ^^^^^
+   |
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: `C` ABI specified multiple times
+  --> $DIR/bad-clobber-abi.rs:15:35
+   |
+LL |         asm!("", clobber_abi("C", "C"));
+   |                              ---  ^^^
+   |                              |
+   |                              previously specified here
+
+error: `win64` ABI specified multiple times
+  --> $DIR/bad-clobber-abi.rs:18:39
+   |
+LL |         asm!("", clobber_abi("win64", "efiapi"));
+   |                              -------  ^^^^^^^^
+   |                              |
+   |                              previously specified here
+   |
+   = note: these ABIs are equivalent on the current target
+
+error: invalid ABI for `clobber_abi`
+  --> $DIR/bad-clobber-abi.rs:20:35
+   |
+LL |         asm!("", clobber_abi("C", "foo", "C"));
+   |                                   ^^^^^
+   |
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: `C` ABI specified multiple times
+  --> $DIR/bad-clobber-abi.rs:20:42
+   |
+LL |         asm!("", clobber_abi("C", "foo", "C"));
+   |                              ---         ^^^
+   |                              |
+   |                              previously specified here
+
+error: invalid ABI for `clobber_abi`
+  --> $DIR/bad-clobber-abi.rs:23:39
+   |
+LL |         asm!("", clobber_abi("win64", "foo", "efiapi"));
+   |                                       ^^^^^
+   |
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: `win64` ABI specified multiple times
+  --> $DIR/bad-clobber-abi.rs:23:46
+   |
+LL |         asm!("", clobber_abi("win64", "foo", "efiapi"));
+   |                              -------         ^^^^^^^^
+   |                              |
+   |                              previously specified here
+   |
+   = note: these ABIs are equivalent on the current target
+
+error: `C` ABI specified multiple times
+  --> $DIR/bad-clobber-abi.rs:26:36
+   |
+LL |         asm!("", clobber_abi("C"), clobber_abi("C"));
+   |                  ----------------  ^^^^^^^^^^^^^^^^
+   |                  |
+   |                  previously specified here
+
+error: `win64` ABI specified multiple times
+  --> $DIR/bad-clobber-abi.rs:29:40
+   |
+LL |         asm!("", clobber_abi("win64"), clobber_abi("efiapi"));
+   |                  --------------------  ^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  previously specified here
+   |
+   = note: these ABIs are equivalent on the current target
+
+error: aborting due to 10 previous errors
+
index dc61d1612e8d64ea640eb889495afb05e90dd011..3facc87641569c6cbe226905c76b94b16a6c4ef1 100644 (file)
@@ -21,6 +21,9 @@ fn main() {
         //~^ ERROR invalid ABI for `clobber_abi`
         asm!("{}", out(reg) foo, clobber_abi("C"));
         //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs
+        asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
+        //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs
+        //~| ERROR `C` ABI specified multiple times
         asm!("", out("eax") foo, clobber_abi("C"));
     }
 }
index 8cfd450ab02a551becd9331c59eaa81f5e29d278..e2351840eef211612b880b82ec4c538f50e3cfeb 100644 (file)
@@ -36,38 +36,47 @@ LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    |
    |                    generic outputs
 
+error: asm with `clobber_abi` must specify explicit registers for outputs
+  --> $DIR/bad-options.rs:24:20
+   |
+LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
+   |                    ^^^^^^^^^^^^  ----------------  ---------------- clobber_abi
+   |                    |             |
+   |                    |             clobber_abi
+   |                    generic outputs
+
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/bad-options.rs:28:25
+  --> $DIR/bad-options.rs:31:25
    |
 LL | global_asm!("", options(nomem));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
-  --> $DIR/bad-options.rs:30:25
+  --> $DIR/bad-options.rs:33:25
    |
 LL | global_asm!("", options(readonly));
    |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
-  --> $DIR/bad-options.rs:32:25
+  --> $DIR/bad-options.rs:35:25
    |
 LL | global_asm!("", options(noreturn));
    |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
-  --> $DIR/bad-options.rs:34:25
+  --> $DIR/bad-options.rs:37:25
    |
 LL | global_asm!("", options(pure));
    |                         ^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
-  --> $DIR/bad-options.rs:36:25
+  --> $DIR/bad-options.rs:39:25
    |
 LL | global_asm!("", options(nostack));
    |                         ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
-  --> $DIR/bad-options.rs:38:25
+  --> $DIR/bad-options.rs:41:25
    |
 LL | global_asm!("", options(preserves_flags));
    |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
@@ -80,5 +89,13 @@ LL |         asm!("", clobber_abi("foo"));
    |
    = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
 
-error: aborting due to 13 previous errors
+error: `C` ABI specified multiple times
+  --> $DIR/bad-options.rs:24:52
+   |
+LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
+   |                                  ----------------  ^^^^^^^^^^^^^^^^
+   |                                  |
+   |                                  previously specified here
+
+error: aborting due to 15 previous errors
 
index 91d0f8c33f9793c58a0d8b37e6e20f7c3a321036..ba4e95db46a2da80e97978aebe43ccf115f132a1 100644 (file)
@@ -1,7 +1,7 @@
 // only-x86_64
 // compile-flags: -C target-feature=+avx2
 
-#![feature(asm)]
+#![feature(asm, asm_const, asm_sym)]
 
 fn main() {
     let mut foo = 0;
index dbf17755720829516155af2e69b864d2952e92ec..c1e4cdbb928f4ce392e6328fcd1e6bda6bbb3d0c 100644 (file)
@@ -3,7 +3,7 @@
 // revisions: mirunsafeck thirunsafeck
 // [thirunsafeck]compile-flags: -Z thir-unsafeck
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn const_generic<const X: usize>() -> usize {
     unsafe {
diff --git a/src/test/ui/asm/x86_64/multiple-clobber-abi.rs b/src/test/ui/asm/x86_64/multiple-clobber-abi.rs
new file mode 100644 (file)
index 0000000..a573d67
--- /dev/null
@@ -0,0 +1,33 @@
+// run-pass
+// needs-asm-support
+// only-x86_64
+
+// Checks that multiple clobber_abi options can be used
+
+#![feature(asm, asm_sym)]
+
+extern "sysv64" fn foo(x: i32) -> i32 {
+    x + 16
+}
+
+extern "win64" fn bar(x: i32) -> i32 {
+    x / 2
+}
+
+fn main() {
+    let x = 8;
+    let y: i32;
+    // call `foo` with `x` as the input, and then `bar` with the output of `foo`
+    // and output that to `y`
+    unsafe {
+        asm!(
+            "call {}; mov rcx, rax; call {}",
+            sym foo,
+            sym bar,
+            in("rdi") x,
+            out("rax") y,
+            clobber_abi("sysv64", "win64"),
+        );
+    }
+    assert_eq!((x, y), (8, 12));
+}
index fa14c52cf0ad7f9fcd43549989d2bbf52d14b4e1..1d6545f1b5c7ad4a658bda4d4781942b4b1faf5b 100644 (file)
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 fn main() {
     let mut foo = 0;
@@ -37,12 +37,14 @@ fn main() {
         asm!("{}", options(), const foo);
         //~^ ERROR arguments are not allowed after options
         //~^^ ERROR attempt to use a non-constant value in a constant
+        asm!("", clobber_abi());
+        //~^ ERROR at least one abi must be provided
         asm!("", clobber_abi(foo));
         //~^ ERROR expected string literal
         asm!("", clobber_abi("C" foo));
-        //~^ ERROR expected `)`, found `foo`
+        //~^ ERROR expected one of `)` or `,`, found `foo`
         asm!("", clobber_abi("C", foo));
-        //~^ ERROR expected `)`, found `,`
+        //~^ ERROR expected string literal
         asm!("{}", clobber_abi("C"), const foo);
         //~^ ERROR arguments are not allowed after clobber_abi
         //~^^ ERROR attempt to use a non-constant value in a constant
@@ -50,8 +52,6 @@ fn main() {
         //~^ ERROR clobber_abi is not allowed after options
         asm!("{}", options(), clobber_abi("C"), const foo);
         //~^ ERROR clobber_abi is not allowed after options
-        asm!("", clobber_abi("C"), clobber_abi("C"));
-        //~^ ERROR clobber_abi specified multiple times
         asm!("{a}", a = const foo, a = const bar);
         //~^ ERROR duplicate argument named `a`
         //~^^ ERROR argument never used
@@ -110,9 +110,9 @@ fn main() {
 global_asm!("", clobber_abi(FOO));
 //~^ ERROR expected string literal
 global_asm!("", clobber_abi("C" FOO));
-//~^ ERROR expected `)`, found `FOO`
+//~^ ERROR expected one of `)` or `,`, found `FOO`
 global_asm!("", clobber_abi("C", FOO));
-//~^ ERROR expected `)`, found `,`
+//~^ ERROR expected string literal
 global_asm!("{}", clobber_abi("C"), const FOO);
 //~^ ERROR arguments are not allowed after clobber_abi
 //~^^ ERROR `clobber_abi` cannot be used with `global_asm!`
@@ -121,7 +121,7 @@ fn main() {
 global_asm!("{}", options(), clobber_abi("C"), const FOO);
 //~^ ERROR clobber_abi is not allowed after options
 global_asm!("", clobber_abi("C"), clobber_abi("C"));
-//~^ ERROR clobber_abi specified multiple times
+//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
 global_asm!("{a}", a = const FOO, a = const BAR);
 //~^ ERROR duplicate argument named `a`
 //~^^ ERROR argument never used
index 91a6baa4afb299e5af43cba7cf43ba893b78bb2e..018df9826c6ee8ebc5d935353945516fb25e2eab 100644 (file)
@@ -90,26 +90,32 @@ LL |         asm!("{}", options(), const foo);
    |                    |
    |                    previous options
 
-error: expected string literal
+error: at least one abi must be provided as an argument to `clobber_abi`
   --> $DIR/parse-error.rs:40:30
    |
+LL |         asm!("", clobber_abi());
+   |                              ^
+
+error: expected string literal
+  --> $DIR/parse-error.rs:42:30
+   |
 LL |         asm!("", clobber_abi(foo));
    |                              ^^^ not a string literal
 
-error: expected `)`, found `foo`
-  --> $DIR/parse-error.rs:42:34
+error: expected one of `)` or `,`, found `foo`
+  --> $DIR/parse-error.rs:44:34
    |
 LL |         asm!("", clobber_abi("C" foo));
-   |                                  ^^^ expected `)`
+   |                                  ^^^ expected one of `)` or `,`
 
-error: expected `)`, found `,`
-  --> $DIR/parse-error.rs:44:33
+error: expected string literal
+  --> $DIR/parse-error.rs:46:35
    |
 LL |         asm!("", clobber_abi("C", foo));
-   |                                 ^ expected `)`
+   |                                   ^^^ not a string literal
 
 error: arguments are not allowed after clobber_abi
-  --> $DIR/parse-error.rs:46:38
+  --> $DIR/parse-error.rs:48:38
    |
 LL |         asm!("{}", clobber_abi("C"), const foo);
    |                    ----------------  ^^^^^^^^^ argument
@@ -117,7 +123,7 @@ LL |         asm!("{}", clobber_abi("C"), const foo);
    |                    clobber_abi
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:49:29
+  --> $DIR/parse-error.rs:51:29
    |
 LL |         asm!("", options(), clobber_abi("C"));
    |                  ---------  ^^^^^^^^^^^^^^^^
@@ -125,21 +131,13 @@ LL |         asm!("", options(), clobber_abi("C"));
    |                  options
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:51:31
+  --> $DIR/parse-error.rs:53:31
    |
 LL |         asm!("{}", options(), clobber_abi("C"), const foo);
    |                    ---------  ^^^^^^^^^^^^^^^^
    |                    |
    |                    options
 
-error: clobber_abi specified multiple times
-  --> $DIR/parse-error.rs:53:36
-   |
-LL |         asm!("", clobber_abi("C"), clobber_abi("C"));
-   |                  ----------------  ^^^^^^^^^^^^^^^^
-   |                  |
-   |                  clobber_abi previously specified here
-
 error: duplicate argument named `a`
   --> $DIR/parse-error.rs:55:36
    |
@@ -300,17 +298,17 @@ error: expected string literal
 LL | global_asm!("", clobber_abi(FOO));
    |                             ^^^ not a string literal
 
-error: expected `)`, found `FOO`
+error: expected one of `)` or `,`, found `FOO`
   --> $DIR/parse-error.rs:112:33
    |
 LL | global_asm!("", clobber_abi("C" FOO));
-   |                                 ^^^ expected `)`
+   |                                 ^^^ expected one of `)` or `,`
 
-error: expected `)`, found `,`
-  --> $DIR/parse-error.rs:114:32
+error: expected string literal
+  --> $DIR/parse-error.rs:114:34
    |
 LL | global_asm!("", clobber_abi("C", FOO));
-   |                                ^ expected `)`
+   |                                  ^^^ not a string literal
 
 error: arguments are not allowed after clobber_abi
   --> $DIR/parse-error.rs:116:37
@@ -342,13 +340,11 @@ LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
    |                   |
    |                   options
 
-error: clobber_abi specified multiple times
-  --> $DIR/parse-error.rs:123:35
+error: `clobber_abi` cannot be used with `global_asm!`
+  --> $DIR/parse-error.rs:123:17
    |
 LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
-   |                 ----------------  ^^^^^^^^^^^^^^^^
-   |                 |
-   |                 clobber_abi previously specified here
+   |                 ^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^
 
 error: duplicate argument named `a`
   --> $DIR/parse-error.rs:125:35
@@ -404,7 +400,7 @@ LL |         asm!("{}", options(), const foo);
    |                                     ^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:46:44
+  --> $DIR/parse-error.rs:48:44
    |
 LL |     let mut foo = 0;
    |      ---------- help: consider using `const` instead of `let`: `const foo`
index 188d03e298e0182b734bb4dce9d5091aaef89589..958dbbdd37646acef7ce8906760ef74f7641b7f8 100644 (file)
@@ -3,7 +3,7 @@
 // only-linux
 // run-pass
 
-#![feature(asm, thread_local)]
+#![feature(asm, thread_local, asm_sym)]
 
 extern "C" fn f1() -> i32 {
     111
@@ -76,5 +76,7 @@ fn main() {
     std::thread::spawn(|| {
         assert_eq!(static_addr!(S1), &S1 as *const u32);
         assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
-    }).join().unwrap();
+    })
+    .join()
+    .unwrap();
 }
index 2311f86d340f48e4db0cc2917b407d44f8f5c216..94aadcf09f423466969d022b754e209d613215ab 100644 (file)
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm, repr_simd, never_type)]
+#![feature(asm, repr_simd, never_type, asm_sym)]
 
 #[repr(simd)]
 struct SimdNonCopy(f32, f32, f32, f32);
index c2c1885ff166f45136a3eb891cbe2d7171387fea..83674cf8204d677f9544166fd938ddbdbc22a21e 100644 (file)
@@ -1,7 +1,7 @@
 // only-x86_64
 // compile-flags: -C target-feature=+avx512f
 
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
 
 use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
 
diff --git a/src/test/ui/associated-types/issue-22066.rs b/src/test/ui/associated-types/issue-22066.rs
new file mode 100644 (file)
index 0000000..8e8ba5d
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+pub trait LineFormatter<'a> {
+    type Iter: Iterator<Item=&'a str> + 'a;
+    fn iter(&'a self, line: &'a str) -> Self::Iter;
+
+    fn dimensions(&'a self, line: &'a str) {
+        let iter: Self::Iter = self.iter(line);
+        <_ as IntoIterator>::into_iter(iter);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-22828.rs b/src/test/ui/associated-types/issue-22828.rs
new file mode 100644 (file)
index 0000000..adf4dd6
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(dead_code)]
+// Test transitive analysis for associated types. Collected types
+// should be normalized and new obligations generated.
+
+// pretty-expanded FIXME #23616
+
+trait Foo {
+    type A;
+    fn foo(&self) {}
+}
+
+impl Foo for usize {
+    type A = usize;
+}
+
+struct Bar<T: Foo> { inner: T::A }
+
+fn is_send<T: Send>() {}
+
+fn main() {
+    is_send::<Bar<usize>>();
+}
diff --git a/src/test/ui/associated-types/issue-28871.rs b/src/test/ui/associated-types/issue-28871.rs
new file mode 100644 (file)
index 0000000..210c783
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+// Regression test for #28871. The problem is that rustc encountered
+// two ways to project, one from a where clause and one from the where
+// clauses on the trait definition. (In fact, in this case, the where
+// clauses originated from the trait definition as well.) The true
+// cause of the error is that the trait definition where clauses are
+// not being normalized, and hence the two sources are considered in
+// conflict, and not a duplicate. Hacky solution is to prefer where
+// clauses over the data found in the trait definition.
+
+trait T {
+    type T;
+}
+
+struct S;
+impl T for S {
+    type T = S;
+}
+
+trait T2 {
+    type T: Iterator<Item=<S as T>::T>;
+}
+
+fn main() { }
diff --git a/src/test/ui/associated-types/issue-47139-1.rs b/src/test/ui/associated-types/issue-47139-1.rs
new file mode 100644 (file)
index 0000000..c55fc34
--- /dev/null
@@ -0,0 +1,78 @@
+// run-pass
+// Regression test for issue #47139:
+//
+// Coherence was encountering an (unnecessary) overflow trying to
+// decide if the two impls of dummy overlap.
+//
+// The overflow went something like:
+//
+// - `&'a ?T: Insertable` ?
+// - let ?T = Option<?U> ?
+// - `Option<?U>: Insertable` ?
+// - `Option<&'a ?U>: Insertable` ?
+// - `&'a ?U: Insertable` ?
+//
+// While somewhere in the middle, a projection would occur, which
+// broke cycle detection.
+//
+// It turned out that this cycle was being kicked off due to some
+// extended diagnostic attempts in coherence, so removing those
+// sidestepped the issue for now.
+
+#![allow(dead_code)]
+
+pub trait Insertable {
+    type Values;
+
+    fn values(self) -> Self::Values;
+}
+
+impl<T> Insertable for Option<T>
+    where
+    T: Insertable,
+    T::Values: Default,
+{
+    type Values = T::Values;
+
+    fn values(self) -> Self::Values {
+        self.map(Insertable::values).unwrap_or_default()
+    }
+}
+
+impl<'a, T> Insertable for &'a Option<T>
+    where
+    Option<&'a T>: Insertable,
+{
+    type Values = <Option<&'a T> as Insertable>::Values;
+
+    fn values(self) -> Self::Values {
+        self.as_ref().values()
+    }
+}
+
+impl<'a, T> Insertable for &'a [T]
+{
+    type Values = Self;
+
+    fn values(self) -> Self::Values {
+        self
+    }
+}
+
+trait Unimplemented { }
+
+trait Dummy { }
+
+struct Foo<T> { t: T }
+
+impl<'a, U> Dummy for Foo<&'a U>
+    where &'a U: Insertable
+{
+}
+
+impl<T> Dummy for T
+    where T: Unimplemented
+{ }
+
+fn main() {
+}
diff --git a/src/test/ui/associated-types/issue-54467.rs b/src/test/ui/associated-types/issue-54467.rs
new file mode 100644 (file)
index 0000000..734bf27
--- /dev/null
@@ -0,0 +1,46 @@
+// run-pass
+
+pub trait Stream {
+    type Item;
+    type Error;
+}
+
+pub trait ParseError<I> {
+    type Output;
+}
+
+impl ParseError<char> for u32 {
+    type Output = ();
+}
+
+impl Stream for () {
+    type Item = char;
+    type Error = u32;
+}
+
+pub struct Lex<'a, I>
+    where I: Stream,
+          I::Error: ParseError<char>,
+          <<I as Stream>::Error as ParseError<char>>::Output: 'a
+{
+    x: &'a <I::Error as ParseError<char>>::Output
+}
+
+pub struct Reserved<'a, I> where
+    I: Stream<Item=char> + 'a,
+    I::Error: ParseError<I::Item>,
+    <<I as Stream>::Error as ParseError<char>>::Output: 'a
+
+{
+    x: Lex<'a, I>
+}
+
+fn main() {
+    let r: Reserved<()> = Reserved {
+        x: Lex {
+            x: &()
+        }
+    };
+
+    let _v = r.x.x;
+}
diff --git a/src/test/ui/async-await/issue-73541-1.rs b/src/test/ui/async-await/issue-73541-1.rs
new file mode 100644 (file)
index 0000000..7fb0d6c
--- /dev/null
@@ -0,0 +1,12 @@
+// edition:2018
+
+fn main() {
+    'a: loop {
+        async {
+            loop {
+                continue 'a
+                //~^ ERROR use of unreachable label `'a`
+            }
+        };
+    }
+}
diff --git a/src/test/ui/async-await/issue-73541-1.stderr b/src/test/ui/async-await/issue-73541-1.stderr
new file mode 100644 (file)
index 0000000..80c1fdf
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0767]: use of unreachable label `'a`
+  --> $DIR/issue-73541-1.rs:7:26
+   |
+LL |     'a: loop {
+   |     -- unreachable label defined here
+...
+LL |                 continue 'a
+   |                          ^^ unreachable label `'a`
+   |
+   = note: labels are unreachable through functions, closures, async blocks and modules
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0767`.
diff --git a/src/test/ui/attributes/issue-40962.rs b/src/test/ui/attributes/issue-40962.rs
new file mode 100644 (file)
index 0000000..7b91c06
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+macro_rules! m {
+    ($i:meta) => {
+        #[derive($i)]
+        struct S;
+    }
+}
+
+m!(Clone);
+
+fn main() {}
index ef59381f5f26dba34697ef81249380f21f2632e7..e59216fe902704879d0eed6b815942532b9ed004 100644 (file)
@@ -19,8 +19,8 @@ error: unexpected token: `{
     let res =
         ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
                                                             &match (&"u8",) {
-                                                                 (arg0,) =>
-                                                                 [::core::fmt::ArgumentV1::new(arg0,
+                                                                 _args =>
+                                                                 [::core::fmt::ArgumentV1::new(_args.0,
                                                                                                ::core::fmt::Display::fmt)],
                                                              }));
     res
diff --git a/src/test/ui/attributes/unrestricted-attribute-tokens.rs b/src/test/ui/attributes/unrestricted-attribute-tokens.rs
new file mode 100644 (file)
index 0000000..e31bc91
--- /dev/null
@@ -0,0 +1,8 @@
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+
+#[rustc_dummy(a b c d)]
+#[rustc_dummy[a b c d]]
+#[rustc_dummy{a b c d}]
+fn main() {}
diff --git a/src/test/ui/auxiliary/changing-crates-a1.rs b/src/test/ui/auxiliary/changing-crates-a1.rs
deleted file mode 100644 (file)
index bc0559b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_name = "a"]
-
-pub fn foo<T>() {}
diff --git a/src/test/ui/auxiliary/changing-crates-a2.rs b/src/test/ui/auxiliary/changing-crates-a2.rs
deleted file mode 100644 (file)
index fafc6d5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_name = "a"]
-
-pub fn foo<T>() { println!("hello!"); }
diff --git a/src/test/ui/auxiliary/changing-crates-b.rs b/src/test/ui/auxiliary/changing-crates-b.rs
deleted file mode 100644 (file)
index f9ce29e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#![crate_name = "b"]
-
-extern crate a;
-
-pub fn foo() { a::foo::<isize>(); }
diff --git a/src/test/ui/auxiliary/legacy-const-generics.rs b/src/test/ui/auxiliary/legacy-const-generics.rs
deleted file mode 100644 (file)
index 67352a2..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(rustc_attrs)]
-
-#[rustc_legacy_const_generics(1)]
-pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
-    [x, Y, z]
-}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols1.rs b/src/test/ui/auxiliary/lto-duplicate-symbols1.rs
deleted file mode 100644 (file)
index ec6d056..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-#[no_mangle]
-pub extern "C" fn foo() {}
diff --git a/src/test/ui/auxiliary/lto-duplicate-symbols2.rs b/src/test/ui/auxiliary/lto-duplicate-symbols2.rs
deleted file mode 100644 (file)
index ec6d056..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-#[no_mangle]
-pub extern "C" fn foo() {}
diff --git a/src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs b/src/test/ui/auxiliary/lto-rustc-loads-linker-plugin.rs
deleted file mode 100644 (file)
index d24375b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// compile-flags: -Clinker-plugin-lto
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
diff --git a/src/test/ui/auxiliary/nested_item.rs b/src/test/ui/auxiliary/nested_item.rs
deleted file mode 100644 (file)
index 9db9d19..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// original problem
-pub fn foo<T>() -> isize {
-    {
-        static foo: isize = 2;
-        foo
-    }
-}
-
-// issue 8134
-struct Foo;
-impl Foo {
-    pub fn foo<T>(&self) {
-        static X: usize = 1;
-    }
-}
-
-// issue 8134
-pub struct Parser<T>(T);
-impl<T: std::iter::Iterator<Item=char>> Parser<T> {
-    fn in_doctype(&mut self) {
-        static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
-    }
-}
-
-struct Bar;
-impl Foo {
-    pub fn bar<T>(&self) {
-        static X: usize = 1;
-    }
-}
diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/bastion-of-the-turbofish.rs
deleted file mode 100644 (file)
index e128570..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// check-pass
-
-// Bastion of the Turbofish
-// ------------------------
-// Beware travellers, lest you venture into waters callous and unforgiving,
-// where hope must be abandoned, ere it is cruelly torn from you. For here
-// stands the bastion of the Turbofish: an impenetrable fortress holding
-// unshaking against those who would dare suggest the supererogation of the
-// Turbofish.
-//
-// Once I was young and foolish and had the impudence to imagine that I could
-// shake free from the coils by which that creature had us tightly bound. I
-// dared to suggest that there was a better way: a brighter future, in which
-// Rustaceans both new and old could be rid of that vile beast. But alas! In
-// my foolhardiness my ignorance was unveiled and my dreams were dashed
-// unforgivingly against the rock of syntactic ambiguity.
-//
-// This humble program, small and insignificant though it might seem,
-// demonstrates that to which we had previously cast a blind eye: an ambiguity
-// in permitting generic arguments to be provided without the consent of the
-// Great Turbofish. Should you be so naïve as to try to revolt against its
-// mighty clutches, here shall its wrath be indomitably displayed. This
-// program must pass for all eternity: forever watched by the guardian angel
-// which gave this beast its name, and stands fundamentally at odds with the
-// impetuous rebellion against the Turbofish.
-//
-// My heart aches in sorrow, for I know I am defeated. Let this be a warning
-// to all those who come after: for they too must overcome the impassible
-// hurdle of defeating the great beast, championed by a resolute winged
-// guardian.
-//
-// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
-// Guardian Angel of these Hallowed Grounds. <3
-
-// See https://github.com/rust-lang/rust/pull/53562
-// and https://github.com/rust-lang/rfcs/pull/2527
-// and https://twitter.com/garblefart/status/1393236602856611843
-// for context.
-
-fn main() {
-    let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
-    let _: (bool, bool) = (the<guardian, stands>(resolute));
-}
diff --git a/src/test/ui/binop/structured-compare.rs b/src/test/ui/binop/structured-compare.rs
new file mode 100644 (file)
index 0000000..63d30c4
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+
+#![allow(non_camel_case_types)]
+
+
+#[derive(Copy, Clone, Debug)]
+enum foo { large, small, }
+
+impl PartialEq for foo {
+    fn eq(&self, other: &foo) -> bool {
+        ((*self) as usize) == ((*other) as usize)
+    }
+    fn ne(&self, other: &foo) -> bool { !(*self).eq(other) }
+}
+
+pub fn main() {
+    let a = (1, 2, 3);
+    let b = (1, 2, 3);
+    assert_eq!(a, b);
+    assert!((a != (1, 2, 4)));
+    assert!((a < (1, 2, 4)));
+    assert!((a <= (1, 2, 4)));
+    assert!(((1, 2, 4) > a));
+    assert!(((1, 2, 4) >= a));
+    let x = foo::large;
+    let y = foo::small;
+    assert!((x != y));
+    assert_eq!(x, foo::large);
+    assert!((x != foo::small));
+}
diff --git a/src/test/ui/borrowck/issue-46095.rs b/src/test/ui/borrowck/issue-46095.rs
new file mode 100644 (file)
index 0000000..59ddb60
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+struct A;
+
+impl A {
+    fn take_mutably(&mut self) {}
+}
+
+fn identity<T>(t: T) -> T {
+    t
+}
+
+// Issue 46095
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Overloaded indexing would cause wrapped to be borrowed mutably
+
+fn main() {
+    let mut a1 = A;
+    let mut a2 = A;
+
+    let wrapped = [&mut a1, &mut a2];
+
+    {
+        wrapped[0 + 1 - 1].take_mutably();
+    }
+
+    {
+        wrapped[identity(0)].take_mutably();
+    }
+}
diff --git a/src/test/ui/box/new-box.rs b/src/test/ui/box/new-box.rs
new file mode 100644 (file)
index 0000000..96a3b19
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+
+fn f(x: Box<isize>) {
+    let y: &isize = &*x;
+    println!("{}", *x);
+    println!("{}", *y);
+}
+
+trait Trait {
+    fn printme(&self);
+}
+
+struct Struct;
+
+impl Trait for Struct {
+    fn printme(&self) {
+        println!("hello world!");
+    }
+}
+
+fn g(x: Box<dyn Trait>) {
+    x.printme();
+    let y: &dyn Trait = &*x;
+    y.printme();
+}
+
+fn main() {
+    f(Box::new(1234));
+    g(Box::new(Struct) as Box<dyn Trait>);
+}
index 339bcfa1060a48e6a3c560176a987535317c2230..2caedb649a35a747accda8d5465a00f90ea82af7 100644 (file)
@@ -53,7 +53,7 @@ fn main() {
         ].clone();
     });
 
-    assert!(result.is_err());
+    assert!(child.is_err());
     assert_eq!(
         1,
         Rc::strong_count(&counter)
diff --git a/src/test/ui/c-variadic/issue-32201.rs b/src/test/ui/c-variadic/issue-32201.rs
new file mode 100644 (file)
index 0000000..f27bb1c
--- /dev/null
@@ -0,0 +1,13 @@
+extern "C" {
+    fn foo(a: i32, ...);
+}
+
+fn bar(_: *const u8) {}
+
+fn main() {
+    unsafe {
+        foo(0, bar);
+        //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
+        //~| HELP cast the value to `fn(*const u8)`
+    }
+}
diff --git a/src/test/ui/c-variadic/issue-32201.stderr b/src/test/ui/c-variadic/issue-32201.stderr
new file mode 100644 (file)
index 0000000..cedb587
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
+  --> $DIR/issue-32201.rs:9:16
+   |
+LL |         foo(0, bar);
+   |                ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0617`.
diff --git a/src/test/ui/cast/supported-cast.rs b/src/test/ui/cast/supported-cast.rs
new file mode 100644 (file)
index 0000000..ff41ce6
--- /dev/null
@@ -0,0 +1,206 @@
+// run-pass
+
+pub fn main() {
+  let f = 1_usize as *const String;
+  println!("{:?}", f as isize);
+  println!("{:?}", f as usize);
+  println!("{:?}", f as i8);
+  println!("{:?}", f as i16);
+  println!("{:?}", f as i32);
+  println!("{:?}", f as i64);
+  println!("{:?}", f as u8);
+  println!("{:?}", f as u16);
+  println!("{:?}", f as u32);
+  println!("{:?}", f as u64);
+
+  println!("{:?}", 1 as isize);
+  println!("{:?}", 1 as usize);
+  println!("{:?}", 1 as *const String);
+  println!("{:?}", 1 as i8);
+  println!("{:?}", 1 as i16);
+  println!("{:?}", 1 as i32);
+  println!("{:?}", 1 as i64);
+  println!("{:?}", 1 as u8);
+  println!("{:?}", 1 as u16);
+  println!("{:?}", 1 as u32);
+  println!("{:?}", 1 as u64);
+  println!("{:?}", 1 as f32);
+  println!("{:?}", 1 as f64);
+
+  println!("{:?}", 1_usize as isize);
+  println!("{:?}", 1_usize as usize);
+  println!("{:?}", 1_usize as *const String);
+  println!("{:?}", 1_usize as i8);
+  println!("{:?}", 1_usize as i16);
+  println!("{:?}", 1_usize as i32);
+  println!("{:?}", 1_usize as i64);
+  println!("{:?}", 1_usize as u8);
+  println!("{:?}", 1_usize as u16);
+  println!("{:?}", 1_usize as u32);
+  println!("{:?}", 1_usize as u64);
+  println!("{:?}", 1_usize as f32);
+  println!("{:?}", 1_usize as f64);
+
+  println!("{:?}", 1i8 as isize);
+  println!("{:?}", 1i8 as usize);
+  println!("{:?}", 1i8 as *const String);
+  println!("{:?}", 1i8 as i8);
+  println!("{:?}", 1i8 as i16);
+  println!("{:?}", 1i8 as i32);
+  println!("{:?}", 1i8 as i64);
+  println!("{:?}", 1i8 as u8);
+  println!("{:?}", 1i8 as u16);
+  println!("{:?}", 1i8 as u32);
+  println!("{:?}", 1i8 as u64);
+  println!("{:?}", 1i8 as f32);
+  println!("{:?}", 1i8 as f64);
+
+  println!("{:?}", 1u8 as isize);
+  println!("{:?}", 1u8 as usize);
+  println!("{:?}", 1u8 as *const String);
+  println!("{:?}", 1u8 as i8);
+  println!("{:?}", 1u8 as i16);
+  println!("{:?}", 1u8 as i32);
+  println!("{:?}", 1u8 as i64);
+  println!("{:?}", 1u8 as u8);
+  println!("{:?}", 1u8 as u16);
+  println!("{:?}", 1u8 as u32);
+  println!("{:?}", 1u8 as u64);
+  println!("{:?}", 1u8 as f32);
+  println!("{:?}", 1u8 as f64);
+
+  println!("{:?}", 1i16 as isize);
+  println!("{:?}", 1i16 as usize);
+  println!("{:?}", 1i16 as *const String);
+  println!("{:?}", 1i16 as i8);
+  println!("{:?}", 1i16 as i16);
+  println!("{:?}", 1i16 as i32);
+  println!("{:?}", 1i16 as i64);
+  println!("{:?}", 1i16 as u8);
+  println!("{:?}", 1i16 as u16);
+  println!("{:?}", 1i16 as u32);
+  println!("{:?}", 1i16 as u64);
+  println!("{:?}", 1i16 as f32);
+  println!("{:?}", 1i16 as f64);
+
+  println!("{:?}", 1u16 as isize);
+  println!("{:?}", 1u16 as usize);
+  println!("{:?}", 1u16 as *const String);
+  println!("{:?}", 1u16 as i8);
+  println!("{:?}", 1u16 as i16);
+  println!("{:?}", 1u16 as i32);
+  println!("{:?}", 1u16 as i64);
+  println!("{:?}", 1u16 as u8);
+  println!("{:?}", 1u16 as u16);
+  println!("{:?}", 1u16 as u32);
+  println!("{:?}", 1u16 as u64);
+  println!("{:?}", 1u16 as f32);
+  println!("{:?}", 1u16 as f64);
+
+  println!("{:?}", 1i32 as isize);
+  println!("{:?}", 1i32 as usize);
+  println!("{:?}", 1i32 as *const String);
+  println!("{:?}", 1i32 as i8);
+  println!("{:?}", 1i32 as i16);
+  println!("{:?}", 1i32 as i32);
+  println!("{:?}", 1i32 as i64);
+  println!("{:?}", 1i32 as u8);
+  println!("{:?}", 1i32 as u16);
+  println!("{:?}", 1i32 as u32);
+  println!("{:?}", 1i32 as u64);
+  println!("{:?}", 1i32 as f32);
+  println!("{:?}", 1i32 as f64);
+
+  println!("{:?}", 1u32 as isize);
+  println!("{:?}", 1u32 as usize);
+  println!("{:?}", 1u32 as *const String);
+  println!("{:?}", 1u32 as i8);
+  println!("{:?}", 1u32 as i16);
+  println!("{:?}", 1u32 as i32);
+  println!("{:?}", 1u32 as i64);
+  println!("{:?}", 1u32 as u8);
+  println!("{:?}", 1u32 as u16);
+  println!("{:?}", 1u32 as u32);
+  println!("{:?}", 1u32 as u64);
+  println!("{:?}", 1u32 as f32);
+  println!("{:?}", 1u32 as f64);
+
+  println!("{:?}", 1i64 as isize);
+  println!("{:?}", 1i64 as usize);
+  println!("{:?}", 1i64 as *const String);
+  println!("{:?}", 1i64 as i8);
+  println!("{:?}", 1i64 as i16);
+  println!("{:?}", 1i64 as i32);
+  println!("{:?}", 1i64 as i64);
+  println!("{:?}", 1i64 as u8);
+  println!("{:?}", 1i64 as u16);
+  println!("{:?}", 1i64 as u32);
+  println!("{:?}", 1i64 as u64);
+  println!("{:?}", 1i64 as f32);
+  println!("{:?}", 1i64 as f64);
+
+  println!("{:?}", 1u64 as isize);
+  println!("{:?}", 1u64 as usize);
+  println!("{:?}", 1u64 as *const String);
+  println!("{:?}", 1u64 as i8);
+  println!("{:?}", 1u64 as i16);
+  println!("{:?}", 1u64 as i32);
+  println!("{:?}", 1u64 as i64);
+  println!("{:?}", 1u64 as u8);
+  println!("{:?}", 1u64 as u16);
+  println!("{:?}", 1u64 as u32);
+  println!("{:?}", 1u64 as u64);
+  println!("{:?}", 1u64 as f32);
+  println!("{:?}", 1u64 as f64);
+
+  println!("{:?}", 1u64 as isize);
+  println!("{:?}", 1u64 as usize);
+  println!("{:?}", 1u64 as *const String);
+  println!("{:?}", 1u64 as i8);
+  println!("{:?}", 1u64 as i16);
+  println!("{:?}", 1u64 as i32);
+  println!("{:?}", 1u64 as i64);
+  println!("{:?}", 1u64 as u8);
+  println!("{:?}", 1u64 as u16);
+  println!("{:?}", 1u64 as u32);
+  println!("{:?}", 1u64 as u64);
+  println!("{:?}", 1u64 as f32);
+  println!("{:?}", 1u64 as f64);
+
+  println!("{:?}", true as isize);
+  println!("{:?}", true as usize);
+  println!("{:?}", true as i8);
+  println!("{:?}", true as i16);
+  println!("{:?}", true as i32);
+  println!("{:?}", true as i64);
+  println!("{:?}", true as u8);
+  println!("{:?}", true as u16);
+  println!("{:?}", true as u32);
+  println!("{:?}", true as u64);
+
+  println!("{:?}", 1f32 as isize);
+  println!("{:?}", 1f32 as usize);
+  println!("{:?}", 1f32 as i8);
+  println!("{:?}", 1f32 as i16);
+  println!("{:?}", 1f32 as i32);
+  println!("{:?}", 1f32 as i64);
+  println!("{:?}", 1f32 as u8);
+  println!("{:?}", 1f32 as u16);
+  println!("{:?}", 1f32 as u32);
+  println!("{:?}", 1f32 as u64);
+  println!("{:?}", 1f32 as f32);
+  println!("{:?}", 1f32 as f64);
+
+  println!("{:?}", 1f64 as isize);
+  println!("{:?}", 1f64 as usize);
+  println!("{:?}", 1f64 as i8);
+  println!("{:?}", 1f64 as i16);
+  println!("{:?}", 1f64 as i32);
+  println!("{:?}", 1f64 as i64);
+  println!("{:?}", 1f64 as u8);
+  println!("{:?}", 1f64 as u16);
+  println!("{:?}", 1f64 as u32);
+  println!("{:?}", 1f64 as u64);
+  println!("{:?}", 1f64 as f32);
+  println!("{:?}", 1f64 as f64);
+}
index d403514b553b079d4ac6c1cb782c6e6742a9dadc..4323e87b08de78e6b261c53c7fc0d653b816fbb4 100644 (file)
@@ -23,11 +23,12 @@ fn test_copy_clone<T: Copy + Clone>(arg: T) {
 fn foo() { }
 
 fn main() {
+    // FIXME: add closures when they're considered WF
     test_copy_clone(foo);
     let f: fn() = foo;
     test_copy_clone(f);
-    // FIXME: add closures when they're considered WF
-    test_copy_clone([1; 56]);
+    // FIXME(#86252): reinstate array test after chalk upgrade
+    //test_copy_clone([1; 56]);
     test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
     test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1));
     test_copy_clone(());
diff --git a/src/test/ui/changing-crates.rs b/src/test/ui/changing-crates.rs
deleted file mode 100644 (file)
index 60c043b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// ignore-msvc FIXME #31306
-
-// note that these aux-build directives must be in this order
-// aux-build:changing-crates-a1.rs
-// aux-build:changing-crates-b.rs
-// aux-build:changing-crates-a2.rs
-// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
-
-extern crate a;
-extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-
-fn main() {}
diff --git a/src/test/ui/changing-crates.stderr b/src/test/ui/changing-crates.stderr
deleted file mode 100644 (file)
index cc62a4d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0460]: found possibly newer version of crate `a` which `b` depends on
-  --> $DIR/changing-crates.rs:10:1
-   |
-LL | extern crate b;
-   | ^^^^^^^^^^^^^^^
-   |
-   = note: perhaps that crate needs to be recompiled?
-   = note: the following crate versions were found:
-           crate `a`: $PATH_a
-           crate `b`: $PATH_b
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/closures/issue-10398.rs b/src/test/ui/closures/issue-10398.rs
new file mode 100644 (file)
index 0000000..0405b2d
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(box_syntax)]
+
+fn main() {
+    let x: Box<_> = box 1;
+    let f = move|| {
+        let _a = x;
+        drop(x);
+        //~^ ERROR: use of moved value: `x`
+    };
+    f();
+}
diff --git a/src/test/ui/closures/issue-10398.stderr b/src/test/ui/closures/issue-10398.stderr
new file mode 100644 (file)
index 0000000..8d9faf3
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/issue-10398.rs:7:14
+   |
+LL |         let _a = x;
+   |                  - value moved here
+LL |         drop(x);
+   |              ^ value used here after move
+   |
+   = note: move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/closures/issue-42463.rs b/src/test/ui/closures/issue-42463.rs
new file mode 100644 (file)
index 0000000..51d6ea3
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+use std::ops::{Deref, DerefMut};
+
+struct CheckedDeref<T, F> {
+    value: T,
+    check: F
+}
+
+impl<F: Fn(&T) -> bool, T> Deref for CheckedDeref<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        assert!((self.check)(&self.value));
+        &self.value
+    }
+}
+
+impl<F: Fn(&T) -> bool, T> DerefMut for CheckedDeref<T, F> {
+    fn deref_mut(&mut self) -> &mut T {
+        assert!((self.check)(&self.value));
+        &mut self.value
+    }
+}
+
+
+fn main() {
+    let mut v = CheckedDeref {
+        value: vec![0],
+        check: |v: &Vec<_>| !v.is_empty()
+    };
+    v.push(1);
+    assert_eq!(*v, vec![0, 1]);
+}
index 36d6450c9a2f0ceb45e23cf0fa4599f3019e9bf2..ee394d64a1dc945d5c072cf2e64f7766771cf292 100644 (file)
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
+                found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
index 91926f233d394d83762aa3472334b10838e306c0..11b9fa7e40caa67f2d1a337f727b8c84a8dc60d4 100644 (file)
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = note: expected unit type `()`
-                found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
+                found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#22t, extern "rust-call" fn(()), _#23t]]`
 help: use parentheses to call this closure
    |
 LL |         let c1 : () = c();
diff --git a/src/test/ui/coercion/auxiliary/issue-39823.rs b/src/test/ui/coercion/auxiliary/issue-39823.rs
new file mode 100644 (file)
index 0000000..3af9c68
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_type="rlib"]
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteC(pub u32);
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteG<T>(pub T);
diff --git a/src/test/ui/coercion/issue-14589.rs b/src/test/ui/coercion/issue-14589.rs
new file mode 100644 (file)
index 0000000..5d8aab2
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+// All 3 expressions should work in that the argument gets
+// coerced to a trait object
+
+// pretty-expanded FIXME #23616
+
+fn main() {
+    send::<Box<dyn Foo>>(Box::new(Output(0)));
+    Test::<Box<dyn Foo>>::foo(Box::new(Output(0)));
+    Test::<Box<dyn Foo>>::new().send(Box::new(Output(0)));
+}
+
+fn send<T>(_: T) {}
+
+struct Test<T> { marker: std::marker::PhantomData<T> }
+impl<T> Test<T> {
+    fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } }
+    fn foo(_: T) {}
+    fn send(&self, _: T) {}
+}
+
+trait Foo { fn dummy(&self) { }}
+struct Output(isize);
+impl Foo for Output {}
diff --git a/src/test/ui/coercion/issue-39823.rs b/src/test/ui/coercion/issue-39823.rs
new file mode 100644 (file)
index 0000000..148cf52
--- /dev/null
@@ -0,0 +1,25 @@
+// run-pass
+// aux-build:issue-39823.rs
+
+extern crate issue_39823;
+use issue_39823::{RemoteC, RemoteG};
+
+#[derive(Debug, PartialEq)]
+struct LocalC(u32);
+
+#[derive(Debug, PartialEq)]
+struct LocalG<T>(T);
+
+fn main() {
+    let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC;
+    assert_eq!(virtual_localc(1), LocalC(1));
+
+    let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG;
+    assert_eq!(virtual_localg(1), LocalG(1));
+
+    let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC;
+    assert_eq!(virtual_remotec(1), RemoteC(1));
+
+    let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG;
+    assert_eq!(virtual_remoteg(1), RemoteG(1));
+}
diff --git a/src/test/ui/coercion/issue-73886.rs b/src/test/ui/coercion/issue-73886.rs
new file mode 100644 (file)
index 0000000..9c0c87a
--- /dev/null
@@ -0,0 +1,6 @@
+fn main() {
+    let _ = &&[0] as &[_];
+    //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]`
+    let _ = 7u32 as Option<_>;
+    //~^ ERROR non-primitive cast: `u32` as `Option<_>`
+}
diff --git a/src/test/ui/coercion/issue-73886.stderr b/src/test/ui/coercion/issue-73886.stderr
new file mode 100644 (file)
index 0000000..a6f8ba6
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
+  --> $DIR/issue-73886.rs:2:13
+   |
+LL |     let _ = &&[0] as &[_];
+   |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error[E0605]: non-primitive cast: `u32` as `Option<_>`
+  --> $DIR/issue-73886.rs:4:13
+   |
+LL |     let _ = 7u32 as Option<_>;
+   |             ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
+   |
+   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0605`.
index 648e290a4b888fa3b30dea17a43e74246abd2462..588630957c94a323b5f98f45a0b64543685792ff 100644 (file)
@@ -6,9 +6,7 @@
 extern crate trait_impl_conflict;
 use trait_impl_conflict::Foo;
 
-impl<A> Foo for A {
-    //~^ ERROR E0119
-    //~| ERROR E0210
+impl<A> Foo for A { //~ ERROR E0210
 }
 
 fn main() {
index d0d86c72ffc68ebe5d11ba76a26e43933cfa83d4..3d253d56a45654bf5b9939524ff579fc4d9146d7 100644 (file)
@@ -1,12 +1,3 @@
-error[E0119]: conflicting implementations of trait `trait_impl_conflict::Foo` for type `isize`
-  --> $DIR/coherence-cross-crate-conflict.rs:9:1
-   |
-LL | impl<A> Foo for A {
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `trait_impl_conflict`:
-           - impl Foo for isize;
-
 error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
   --> $DIR/coherence-cross-crate-conflict.rs:9:6
    |
@@ -16,7 +7,6 @@ LL | impl<A> Foo for A {
    = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0119, E0210.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0210`.
index c364c707ff9eac202517a2a371fc43b01b498760..912891480790ee141f1e7c0deda860ef875d271c 100644 (file)
@@ -1,15 +1,3 @@
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
-   |
-LL | impl !Marker1 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
-
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
-   |
-LL | impl !Marker2 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1
    |
@@ -33,6 +21,18 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | impl !Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
+   |
+LL | impl !Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
+   |
+LL | impl !Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
index b80429794f92cb2b76eddef9a4657600934ad36c..056198374a4cc1e0caff6754ae35d49263aeaaf7 100644 (file)
@@ -1,15 +1,3 @@
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
-   |
-LL | impl Marker1 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
-
-error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
-   |
-LL | impl Marker2 for dyn Object + Marker2 { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1
    |
@@ -33,6 +21,18 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | unsafe impl Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
+   |
+LL | impl Marker1 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+
+error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
+   |
+LL | impl Marker2 for dyn Object + Marker2 { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
index a86ca0e5eacdc00df8a8c49583020017fa94e7a9..4204fecc37e15d4053372d3876aa14a439d67915 100644 (file)
@@ -3,8 +3,7 @@
 use std::marker::Copy;
 
 impl Copy for i32 {}
-//~^ ERROR E0119
-//~| ERROR E0117
+//~^ ERROR E0117
 enum TestE {
   A
 }
@@ -32,7 +31,6 @@ impl Copy for [MyType] {}
 //~^ ERROR E0206
 //~| ERROR E0117
 impl Copy for &'static [NotSync] {}
-//~^ ERROR E0119
-//~| ERROR E0117
+//~^ ERROR E0117
 fn main() {
 }
index 2ac0706d72e57cf24e1207e190dbb0cf10fdce61..a7d6968a2967cc272de8e7fcb712ca75b96c8574 100644 (file)
@@ -1,50 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `i32`
-  --> $DIR/coherence-impls-copy.rs:5:1
-   |
-LL | impl Copy for i32 {}
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl Copy for i32;
-
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`
-  --> $DIR/coherence-impls-copy.rs:29:1
-   |
-LL | impl Copy for &'static NotSync {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Copy for &T
-             where T: ?Sized;
-
-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`
-  --> $DIR/coherence-impls-copy.rs:34:1
-   |
-LL | impl Copy for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Copy for &T
-             where T: ?Sized;
-
-error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/coherence-impls-copy.rs:22:15
-   |
-LL | impl Copy for &'static mut MyType {}
-   |               ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
-
-error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/coherence-impls-copy.rs:26:15
-   |
-LL | impl Copy for (MyType, MyType) {}
-   |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
-
-error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/coherence-impls-copy.rs:31:15
-   |
-LL | impl Copy for [MyType] {}
-   |               ^^^^^^^^ type is not a structure or enumeration
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impls-copy.rs:5:1
    |
@@ -57,7 +10,7 @@ LL | impl Copy for i32 {}
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:26:1
+  --> $DIR/coherence-impls-copy.rs:25:1
    |
 LL | impl Copy for (MyType, MyType) {}
    | ^^^^^^^^^^^^^^----------------
@@ -68,7 +21,7 @@ LL | impl Copy for (MyType, MyType) {}
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:31:1
+  --> $DIR/coherence-impls-copy.rs:30:1
    |
 LL | impl Copy for [MyType] {}
    | ^^^^^^^^^^^^^^--------
@@ -79,7 +32,7 @@ LL | impl Copy for [MyType] {}
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-copy.rs:34:1
+  --> $DIR/coherence-impls-copy.rs:33:1
    |
 LL | impl Copy for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^------------------
@@ -89,7 +42,35 @@ LL | impl Copy for &'static [NotSync] {}
    |
    = note: define and implement a trait or new type instead
 
-error: aborting due to 10 previous errors
+error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&NotSync`
+  --> $DIR/coherence-impls-copy.rs:28:1
+   |
+LL | impl Copy for &'static NotSync {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T> Copy for &T
+             where T: ?Sized;
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:21:15
+   |
+LL | impl Copy for &'static mut MyType {}
+   |               ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:25:15
+   |
+LL | impl Copy for (MyType, MyType) {}
+   |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
+
+error[E0206]: the trait `Copy` may not be implemented for this type
+  --> $DIR/coherence-impls-copy.rs:30:15
+   |
+LL | impl Copy for [MyType] {}
+   |               ^^^^^^^^ type is not a structure or enumeration
+
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0117, E0119, E0206.
 For more information about an error, try `rustc --explain E0117`.
index e00cb9a7c5b5104e4d6dd71ad5f17b346ff3a348..b7b57c602b8d134ceab984111fc7771ff7794143 100644 (file)
@@ -23,7 +23,6 @@ unsafe impl Send for [MyType] {}
 //~^ ERROR E0117
 
 unsafe impl Send for &'static [NotSync] {}
-//~^ ERROR conflicting implementations of trait
-//~| ERROR only traits defined in the current crate
+//~^ ERROR only traits defined in the current crate
 
 fn main() {}
index 46e9e7e986c3432da3abb4afd27bc40adf157c76..dd1fd1b0dce24ff54448a062599d2d9c8a2f66cd 100644 (file)
@@ -1,14 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::marker::Send` for type `&[NotSync]`
-  --> $DIR/coherence-impls-send.rs:25:1
-   |
-LL | unsafe impl Send for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Send for &T
-             where T: Sync, T: ?Sized;
-   = note: upstream crates may add a new impl of trait `std::marker::Sync` for type `[NotSync]` in future versions
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/coherence-impls-send.rs:16:1
    |
@@ -48,7 +37,7 @@ LL | unsafe impl Send for &'static [NotSync] {}
    |
    = note: define and implement a trait or new type instead
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0117, E0119, E0321.
+Some errors have detailed explanations: E0117, E0321.
 For more information about an error, try `rustc --explain E0117`.
index 3b0a9fc60a2e070fc2e8a2a9d685e6516472016f..9cf5ed38c9c6bf8a838f6126934db39a1aae2058 100644 (file)
@@ -1,3 +1,36 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:20:1
+   |
+LL | impl Sized for (MyType, MyType) {}
+   | ^^^^^^^^^^^^^^^----------------
+   | |              |
+   | |              this is not defined in the current crate because tuples are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:27:1
+   |
+LL | impl Sized for [MyType] {}
+   | ^^^^^^^^^^^^^^^--------
+   | |              |
+   | |              this is not defined in the current crate because slices are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/coherence-impls-sized.rs:31:1
+   |
+LL | impl Sized for &'static [NotSync] {}
+   | ^^^^^^^^^^^^^^^------------------
+   | |              |
+   | |              this is not defined in the current crate because slices are always foreign
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
 error[E0322]: explicit impls for the `Sized` trait are not permitted
   --> $DIR/coherence-impls-sized.rs:14:1
    |
@@ -34,39 +67,6 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted
 LL | impl Sized for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:20:1
-   |
-LL | impl Sized for (MyType, MyType) {}
-   | ^^^^^^^^^^^^^^^----------------
-   | |              |
-   | |              this is not defined in the current crate because tuples are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:27:1
-   |
-LL | impl Sized for [MyType] {}
-   | ^^^^^^^^^^^^^^^--------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impls-sized.rs:31:1
-   |
-LL | impl Sized for &'static [NotSync] {}
-   | ^^^^^^^^^^^^^^^------------------
-   | |              |
-   | |              this is not defined in the current crate because slices are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
 error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0117, E0322.
index 52d2cc88cbe7f2668ad6484b3c829d0053d95668..051a519ee1477dec0fefa272b51f28d0bcbd7963 100644 (file)
@@ -1,22 +1,22 @@
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-orphan.rs:10:1
+  --> $DIR/coherence-orphan.rs:17:1
    |
-LL | impl TheTrait<usize> for isize { }
-   | ^^^^^---------------^^^^^-----
-   | |    |                   |
-   | |    |                   `isize` is not defined in the current crate
-   | |    `usize` is not defined in the current crate
+LL | impl !Send for Vec<isize> { }
+   | ^^^^^^^^^^^^^^^----------
+   | |              |
+   | |              `Vec` is not defined in the current crate
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-orphan.rs:17:1
+  --> $DIR/coherence-orphan.rs:10:1
    |
-LL | impl !Send for Vec<isize> { }
-   | ^^^^^^^^^^^^^^^----------
-   | |              |
-   | |              `Vec` is not defined in the current crate
+LL | impl TheTrait<usize> for isize { }
+   | ^^^^^---------------^^^^^-----
+   | |    |                   |
+   | |    |                   `isize` is not defined in the current crate
+   | |    `usize` is not defined in the current crate
    | impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
index 10a8b19159e02bfb2542844c248f8cd2da03f252..61914e2293070459c03ee0a6c66edf2975e7829a 100644 (file)
@@ -8,6 +8,8 @@
 // ignore-sgx no processes
 #![feature(process_exec, rustc_private)]
 
+extern crate libc;
+
 use std::env;
 use std::io::Error;
 use std::os::unix::process::CommandExt;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::Arc;
 
-#[cfg(not(target_os = "linux"))]
-fn getpid() -> u32 {
-    use std::process;
-    process::id()
-}
-
-/// We need to directly use the getpid syscall instead of using `process::id()`
-/// because the libc wrapper might return incorrect values after a process was
-/// forked.
-#[cfg(target_os = "linux")]
-fn getpid() -> u32 {
-    extern crate libc;
-    unsafe {
-        libc::syscall(libc::SYS_getpid) as _
-    }
-}
-
 fn main() {
     if let Some(arg) = env::args().nth(1) {
         match &arg[..] {
@@ -83,12 +68,14 @@ fn main() {
     };
     assert_eq!(output.raw_os_error(), Some(102));
 
-    let pid = getpid();
+    let pid = unsafe { libc::getpid() };
+    assert!(pid >= 0);
     let output = unsafe {
         Command::new(&me)
             .arg("empty")
             .pre_exec(move || {
-                let child = getpid();
+                let child = libc::getpid();
+                assert!(child >= 0);
                 assert!(pid != child);
                 Ok(())
             })
diff --git a/src/test/ui/compare-method/issue-90444.rs b/src/test/ui/compare-method/issue-90444.rs
new file mode 100644 (file)
index 0000000..6c287d9
--- /dev/null
@@ -0,0 +1,17 @@
+pub struct A;
+impl From<fn((), (), &())> for A {
+    fn from(_: fn((), (), &mut ())) -> Self {
+        //~^ error: method `from` has an incompatible type for trait
+        loop {}
+    }
+}
+
+pub struct B;
+impl From<fn((), (), u32)> for B {
+    fn from(_: fn((), (), u64)) -> Self {
+        //~^ error: method `from` has an incompatible type for trait
+        loop {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr
new file mode 100644 (file)
index 0000000..84bbec0
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0053]: method `from` has an incompatible type for trait
+  --> $DIR/issue-90444.rs:3:16
+   |
+LL |     fn from(_: fn((), (), &mut ())) -> Self {
+   |                ^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                types differ in mutability
+   |                help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())`
+   |
+   = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A`
+              found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A`
+
+error[E0053]: method `from` has an incompatible type for trait
+  --> $DIR/issue-90444.rs:11:16
+   |
+LL |     fn from(_: fn((), (), u64)) -> Self {
+   |                ^^^^^^^^^^^^^^^
+   |                |
+   |                expected `u32`, found `u64`
+   |                help: change the parameter type to match the trait: `fn((), (), u32)`
+   |
+   = note: expected fn pointer `fn(fn((), (), u32)) -> B`
+              found fn pointer `fn(fn((), (), u64)) -> B`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/conditional-compilation/issue-34028.rs b/src/test/ui/conditional-compilation/issue-34028.rs
new file mode 100644 (file)
index 0000000..d761c0c
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+macro_rules! m {
+    () => { #[cfg(any())] fn f() {} }
+}
+
+trait T {}
+impl T for () { m!(); }
+
+fn main() {}
diff --git a/src/test/ui/const-generics/auxiliary/legacy-const-generics.rs b/src/test/ui/const-generics/auxiliary/legacy-const-generics.rs
new file mode 100644 (file)
index 0000000..67352a2
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[rustc_legacy_const_generics(1)]
+pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+    [x, Y, z]
+}
index 6268a564b06b65dafeccf91f5a895788ddf3ba7c..87e4ad500404439b6fa4c585653f292c0fee2d7c 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
    |                    ^^^^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/legacy-const-generics-bad.rs b/src/test/ui/const-generics/legacy-const-generics-bad.rs
new file mode 100644 (file)
index 0000000..538eee3
--- /dev/null
@@ -0,0 +1,16 @@
+// aux-build:legacy-const-generics.rs
+
+extern crate legacy_const_generics;
+
+fn foo<const N: usize>() {
+    let a = 1;
+    legacy_const_generics::foo(0, a, 2);
+    //~^ ERROR attempt to use a non-constant value in a constant
+
+    legacy_const_generics::foo(0, N, 2);
+
+    legacy_const_generics::foo(0, N + 1, 2);
+    //~^ ERROR generic parameters may not be used in const operations
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/legacy-const-generics-bad.stderr b/src/test/ui/const-generics/legacy-const-generics-bad.stderr
new file mode 100644 (file)
index 0000000..3c78dd6
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/legacy-const-generics-bad.rs:7:35
+   |
+LL |     let a = 1;
+   |     ----- help: consider using `const` instead of `let`: `const a`
+LL |     legacy_const_generics::foo(0, a, 2);
+   |                                   ^ non-constant value
+
+error: generic parameters may not be used in const operations
+  --> $DIR/legacy-const-generics-bad.rs:12:35
+   |
+LL |     legacy_const_generics::foo(0, N + 1, 2);
+   |                                   ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/const-generics/legacy-const-generics.rs b/src/test/ui/const-generics/legacy-const-generics.rs
new file mode 100644 (file)
index 0000000..9abc72d
--- /dev/null
@@ -0,0 +1,18 @@
+// aux-build:legacy-const-generics.rs
+// run-pass
+
+#![feature(rustc_attrs)]
+
+extern crate legacy_const_generics;
+
+#[rustc_legacy_const_generics(1)]
+pub fn bar<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+    [x, Y, z]
+}
+
+fn main() {
+    assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]);
+    assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]);
+    // FIXME: Only works cross-crate
+    //assert_eq!(bar(0, 1, 2), [0, 1, 2]);
+}
index fa9542f93a36ce67cf62727a2385a64db846182b..b46ca6ba6df5464a5137e942b743cc5143e2b4cb 100644 (file)
@@ -1,3 +1,5 @@
+// needs-asm-support
+
 #![feature(asm)]
 
 const _: () = unsafe { asm!("nop") };
index f38044a290b631da4b46675ee0b92676a415c30e..65a828d118c0cdc70a2e487d7d4f0873fde6c47b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: inline assembly is not allowed in constants
-  --> $DIR/inline_asm.rs:3:24
+  --> $DIR/inline_asm.rs:5:24
    |
 LL | const _: () = unsafe { asm!("nop") };
    |                        ^^^^^^^^^^^
diff --git a/src/test/ui/consts/issue-13902.rs b/src/test/ui/consts/issue-13902.rs
new file mode 100644 (file)
index 0000000..1afde0e
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
+const JSVAL_TYPE_INT32: u8 = 0x01;
+const JSVAL_TYPE_UNDEFINED: u8 = 0x02;
+#[repr(u32)]
+enum ValueTag {
+    JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32),
+    JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32),
+}
+
+fn main() {
+    let _ = ValueTag::JSVAL_TAG_INT32;
+}
diff --git a/src/test/ui/consts/issue-17074.rs b/src/test/ui/consts/issue-17074.rs
new file mode 100644 (file)
index 0000000..0ed8113
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(dead_code)]
+
+static X2: u64 = !0 as u16 as u64;
+static Y2: u64 = !0 as u32 as u64;
+const X: u64 = !0 as u16 as u64;
+const Y: u64 = !0 as u32 as u64;
+
+fn main() {
+    assert_eq!(match 1 {
+        X => unreachable!(),
+        Y => unreachable!(),
+        _ => 1
+    }, 1);
+}
diff --git a/src/test/ui/consts/issue-18294.rs b/src/test/ui/consts/issue-18294.rs
new file mode 100644 (file)
index 0000000..77355f0
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    const X: u32 = 1;
+    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
+    println!("{}", Y);
+}
diff --git a/src/test/ui/consts/issue-18294.stderr b/src/test/ui/consts/issue-18294.stderr
new file mode 100644 (file)
index 0000000..e0cbd2a
--- /dev/null
@@ -0,0 +1,11 @@
+error: pointers cannot be cast to integers during const eval
+  --> $DIR/issue-18294.rs:3:31
+   |
+LL |     const Y: usize = unsafe { &X as *const u32 as usize };
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: at compile-time, pointers do not have an integer value
+   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/issue-23968-const-not-overflow.rs b/src/test/ui/consts/issue-23968-const-not-overflow.rs
new file mode 100644 (file)
index 0000000..b959302
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+const U8_MAX_HALF: u8 = !0u8 / 2;
+const U16_MAX_HALF: u16 = !0u16 / 2;
+const U32_MAX_HALF: u32 = !0u32 / 2;
+const U64_MAX_HALF: u64 = !0u64 / 2;
+
+fn main() {
+    assert_eq!(U8_MAX_HALF, 0x7f);
+    assert_eq!(U16_MAX_HALF, 0x7fff);
+    assert_eq!(U32_MAX_HALF, 0x7fff_ffff);
+    assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff);
+}
diff --git a/src/test/ui/consts/issue-37550-1.rs b/src/test/ui/consts/issue-37550-1.rs
new file mode 100644 (file)
index 0000000..35b63bd
--- /dev/null
@@ -0,0 +1,6 @@
+const fn x() {
+    let t = true;
+    let x = || t; //~ ERROR function pointer
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-37550-1.stderr b/src/test/ui/consts/issue-37550-1.stderr
new file mode 100644 (file)
index 0000000..f66d706
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: function pointers cannot appear in constant functions
+  --> $DIR/issue-37550-1.rs:3:9
+   |
+LL |     let x = || t;
+   |         ^
+   |
+   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/issue-37991.rs b/src/test/ui/consts/issue-37991.rs
new file mode 100644 (file)
index 0000000..a6ac4d5
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+
+const fn foo() -> i64 {
+    3
+}
+
+const fn bar(x: i64) -> i64 {
+    x*2
+}
+
+fn main() {
+    let val = &(foo() % 2);
+    assert_eq!(*val, 1);
+
+    let val2 = &(bar(1+1) % 3);
+    assert_eq!(*val2, 1);
+}
diff --git a/src/test/ui/crate-loading/auxiliary/libfoo.rlib b/src/test/ui/crate-loading/auxiliary/libfoo.rlib
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/test/ui/crate-loading/invalid-rlib.rs b/src/test/ui/crate-loading/invalid-rlib.rs
new file mode 100644 (file)
index 0000000..77c2909
--- /dev/null
@@ -0,0 +1,8 @@
+// compile-flags: --crate-type lib --extern foo={{src-base}}/crate-loading/auxiliary/libfoo.rlib
+// normalize-stderr-test: "failed to mmap file '.*auxiliary/libfoo.rlib':.*" -> "failed to mmap file 'auxiliary/libfoo.rlib'"
+// don't emit warn logging, it's basically the same as the errors and it's annoying to normalize
+// rustc-env:RUSTC_LOG=error
+// edition:2018
+#![no_std]
+use ::foo; //~ ERROR invalid metadata files for crate `foo`
+//~| NOTE failed to mmap file
diff --git a/src/test/ui/crate-loading/invalid-rlib.stderr b/src/test/ui/crate-loading/invalid-rlib.stderr
new file mode 100644 (file)
index 0000000..b2c79f7
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0786]: found invalid metadata files for crate `foo`
+  --> $DIR/invalid-rlib.rs:7:7
+   |
+LL | use ::foo;
+   |       ^^^
+   |
+   = note: failed to mmap file 'auxiliary/libfoo.rlib'
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0786`.
index 35e42a6857f320cfa429c639e4ae9d6069f538d2..9bde2ca1942e64c09a188bc4d2a58f835ffaa762 100644 (file)
@@ -278,6 +278,7 @@ fn test() {
         let _ = nested::DeprecatedStruct {
             //~^ ERROR use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
             i: 0 //~ ERROR use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text
+            //~| ERROR field `i` of struct `this_crate::nested::DeprecatedStruct` is private
         };
 
         let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
index 20af4f62e6502cc78af28a3b2bf97afcd8878bd6..5d716fa625e5d47793dd0a2e878be4296b3a627f 100644 (file)
@@ -257,97 +257,97 @@ LL |         let _ = nested::DeprecatedStruct {
    |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
-  --> $DIR/deprecation-lint.rs:283:25
+  --> $DIR/deprecation-lint.rs:284:25
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
    |                         ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:285:31
+  --> $DIR/deprecation-lint.rs:286:31
    |
 LL | ...   let _ = nested::Enum::DeprecatedVariant;
    |                             ^^^^^^^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
-  --> $DIR/deprecation-lint.rs:287:25
+  --> $DIR/deprecation-lint.rs:288:25
    |
 LL | ...   let _ = nested::DeprecatedTupleStruct (1);
    |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:292:16
+  --> $DIR/deprecation-lint.rs:293:16
    |
 LL |         Trait::trait_deprecated(&foo);
    |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:294:25
+  --> $DIR/deprecation-lint.rs:295:25
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |                         ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:296:16
+  --> $DIR/deprecation-lint.rs:297:16
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:298:25
+  --> $DIR/deprecation-lint.rs:299:25
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
    |                       ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar`
-  --> $DIR/deprecation-lint.rs:316:13
+  --> $DIR/deprecation-lint.rs:317:13
    |
 LL |             bar();
    |             ^^^
 
 error: use of deprecated trait `this_crate::DeprecatedTrait`: text
-  --> $DIR/deprecation-lint.rs:335:10
+  --> $DIR/deprecation-lint.rs:336:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
 error: use of deprecated trait `this_crate::DeprecatedTrait`: text
-  --> $DIR/deprecation-lint.rs:337:24
+  --> $DIR/deprecation-lint.rs:338:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:389:17
+  --> $DIR/deprecation-lint.rs:390:17
    |
 LL |         let x = Deprecated {
    |                 ^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:398:13
+  --> $DIR/deprecation-lint.rs:399:13
    |
 LL |         let Deprecated {
    |             ^^^^^^^^^^
 
 error: use of deprecated struct `this_crate2::Deprecated`: text
-  --> $DIR/deprecation-lint.rs:404:13
+  --> $DIR/deprecation-lint.rs:405:13
    |
 LL |         let Deprecated
    |             ^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:409:17
+  --> $DIR/deprecation-lint.rs:410:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
    |                 ^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:419:13
+  --> $DIR/deprecation-lint.rs:420:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
-  --> $DIR/deprecation-lint.rs:428:13
+  --> $DIR/deprecation-lint.rs:429:13
    |
 LL |         let Deprecated2
    |             ^^^^^^^^^^^
@@ -617,124 +617,131 @@ LL |             i: 0
    |             ^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:291:13
+  --> $DIR/deprecation-lint.rs:292:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:293:16
+  --> $DIR/deprecation-lint.rs:294:16
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |                ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:295:13
+  --> $DIR/deprecation-lint.rs:296:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:297:16
+  --> $DIR/deprecation-lint.rs:298:16
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |                ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:302:13
+  --> $DIR/deprecation-lint.rs:303:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:303:13
+  --> $DIR/deprecation-lint.rs:304:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:362:13
+  --> $DIR/deprecation-lint.rs:363:13
    |
 LL |             override2: 3,
    |             ^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:366:17
+  --> $DIR/deprecation-lint.rs:367:17
    |
 LL |         let _ = x.override2;
    |                 ^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable::override2`: text
-  --> $DIR/deprecation-lint.rs:370:13
+  --> $DIR/deprecation-lint.rs:371:13
    |
 LL |             override2: _
    |             ^^^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Stable2::2`: text
-  --> $DIR/deprecation-lint.rs:378:17
+  --> $DIR/deprecation-lint.rs:379:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Stable2::2`: text
-  --> $DIR/deprecation-lint.rs:383:20
+  --> $DIR/deprecation-lint.rs:384:20
    |
 LL |                    _)
    |                    ^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:391:13
+  --> $DIR/deprecation-lint.rs:392:13
    |
 LL |             inherit: 1,
    |             ^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:395:17
+  --> $DIR/deprecation-lint.rs:396:17
    |
 LL |         let _ = x.inherit;
    |                 ^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated::inherit`: text
-  --> $DIR/deprecation-lint.rs:400:13
+  --> $DIR/deprecation-lint.rs:401:13
    |
 LL |             inherit: _,
    |             ^^^^^^^^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::0`: text
-  --> $DIR/deprecation-lint.rs:412:17
+  --> $DIR/deprecation-lint.rs:413:17
    |
 LL |         let _ = x.0;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::1`: text
-  --> $DIR/deprecation-lint.rs:414:17
+  --> $DIR/deprecation-lint.rs:415:17
    |
 LL |         let _ = x.1;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::2`: text
-  --> $DIR/deprecation-lint.rs:416:17
+  --> $DIR/deprecation-lint.rs:417:17
    |
 LL |         let _ = x.2;
    |                 ^^^
 
 error: use of deprecated field `this_crate2::Deprecated2::0`: text
-  --> $DIR/deprecation-lint.rs:421:14
+  --> $DIR/deprecation-lint.rs:422:14
    |
 LL |             (_,
    |              ^
 
 error: use of deprecated field `this_crate2::Deprecated2::1`: text
-  --> $DIR/deprecation-lint.rs:423:14
+  --> $DIR/deprecation-lint.rs:424:14
    |
 LL |              _,
    |              ^
 
 error: use of deprecated field `this_crate2::Deprecated2::2`: text
-  --> $DIR/deprecation-lint.rs:425:14
+  --> $DIR/deprecation-lint.rs:426:14
    |
 LL |              _)
    |              ^
 
-error: aborting due to 122 previous errors
+error[E0451]: field `i` of struct `this_crate::nested::DeprecatedStruct` is private
+  --> $DIR/deprecation-lint.rs:280:13
+   |
+LL |             i: 0
+   |             ^^^^ private field
+
+error: aborting due to 123 previous errors
 
+For more information about this error, try `rustc --explain E0451`.
diff --git a/src/test/ui/deprecation/try-macro-suggestion.rs b/src/test/ui/deprecation/try-macro-suggestion.rs
new file mode 100644 (file)
index 0000000..635ceac
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: --edition 2018
+fn foo() -> Result<(), ()> {
+    Ok(try!()); //~ ERROR use of deprecated `try` macro
+    Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
+}
+
+fn main() {
+    let _ = foo();
+}
diff --git a/src/test/ui/deprecation/try-macro-suggestion.stderr b/src/test/ui/deprecation/try-macro-suggestion.stderr
new file mode 100644 (file)
index 0000000..c7dde7e
--- /dev/null
@@ -0,0 +1,31 @@
+error: use of deprecated `try` macro
+  --> $DIR/try-macro-suggestion.rs:3:8
+   |
+LL |     Ok(try!());
+   |        ^^^^^^
+   |
+   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
+help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax
+   |
+LL |     Ok(r#try!());
+   |        ++
+
+error: use of deprecated `try` macro
+  --> $DIR/try-macro-suggestion.rs:4:8
+   |
+LL |     Ok(try!(Ok(())))
+   |        ^^^^^^^^^^^^
+   |
+   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
+help: you can use the `?` operator instead
+   |
+LL -     Ok(try!(Ok(())))
+LL +     Ok(Ok(())?)
+   | 
+help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax
+   |
+LL |     Ok(r#try!(Ok(())))
+   |        ++
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/deriving/issue-19358.rs b/src/test/ui/deriving/issue-19358.rs
new file mode 100644 (file)
index 0000000..3970a41
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+
+#![allow(dead_code)]
+
+trait Trait { fn dummy(&self) { } }
+
+#[derive(Debug)]
+struct Foo<T: Trait> {
+    foo: T,
+}
+
+#[derive(Debug)]
+struct Bar<T> where T: Trait {
+    bar: T,
+}
+
+impl Trait for isize {}
+
+fn main() {
+    let a = Foo { foo: 12 };
+    let b = Bar { bar: 12 };
+    println!("{:?} {:?}", a, b);
+}
diff --git a/src/test/ui/deriving/issue-58319.rs b/src/test/ui/deriving/issue-58319.rs
new file mode 100644 (file)
index 0000000..757307d
--- /dev/null
@@ -0,0 +1,621 @@
+// run-pass
+fn main() {}
+#[derive(Clone)]
+pub struct Little;
+#[derive(Clone)]
+pub struct Big(
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+    Little,
+);
diff --git a/src/test/ui/diverging-tuple-parts-39485.rs b/src/test/ui/diverging-tuple-parts-39485.rs
deleted file mode 100644 (file)
index 0cde611..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// After #39485, this test used to pass, but that change was reverted
-// due to numerous inference failures like #39808, so it now fails
-// again. #39485 made it so that diverging types never propagate
-// upward; but we now do propagate such types upward in many more
-// cases.
-
-fn g() {
-    &panic!() //~ ERROR mismatched types
-}
-
-fn f() -> isize {
-    (return 1, return 2) //~ ERROR mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/diverging-tuple-parts-39485.stderr b/src/test/ui/diverging-tuple-parts-39485.stderr
deleted file mode 100644 (file)
index 32967b3..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/diverging-tuple-parts-39485.rs:8:5
-   |
-LL |     &panic!()
-   |     ^^^^^^^^^ expected `()`, found reference
-   |
-   = note: expected unit type `()`
-              found reference `&_`
-help: try adding a return type
-   |
-LL | fn g() -> &_ {
-   |        +++++
-help: consider removing the borrow
-   |
-LL -     &panic!()
-LL +     panic!()
-   | 
-
-error[E0308]: mismatched types
-  --> $DIR/diverging-tuple-parts-39485.rs:12:5
-   |
-LL | fn f() -> isize {
-   |           ----- expected `isize` because of return type
-LL |     (return 1, return 2)
-   |     ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
-   |
-   = note: expected type `isize`
-             found tuple `(!, !)`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/drop/issue-35546.rs b/src/test/ui/drop/issue-35546.rs
new file mode 100644 (file)
index 0000000..004679a
--- /dev/null
@@ -0,0 +1,20 @@
+// build-pass
+#![allow(dead_code)]
+// Regression test for #35546. Check that we are able to codegen
+// this. Before we had problems because of the drop glue signature
+// around dropping a trait object (specifically, when dropping the
+// `value` field of `Node<Send>`).
+
+struct Node<T: ?Sized + Send> {
+    next: Option<Box<Node<dyn Send>>>,
+    value: T,
+}
+
+fn clear(head: &mut Option<Box<Node<dyn Send>>>) {
+    match head.take() {
+        Some(node) => *head = node.next,
+        None => (),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/drop/terminate-in-initializer.rs b/src/test/ui/drop/terminate-in-initializer.rs
new file mode 100644 (file)
index 0000000..c9cb932
--- /dev/null
@@ -0,0 +1,33 @@
+// run-pass
+// ignore-emscripten no threads support
+
+// Issue #787
+// Don't try to clean up uninitialized locals
+
+
+use std::thread;
+
+fn test_break() { loop { let _x: Box<isize> = break; } }
+
+fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box<isize> = continue; } }
+
+fn test_ret() { let _x: Box<isize> = return; }
+
+fn test_panic() {
+    fn f() { let _x: Box<isize> = panic!(); }
+    thread::spawn(move|| f() ).join().unwrap_err();
+}
+
+fn test_panic_indirect() {
+    fn f() -> ! { panic!(); }
+    fn g() { let _x: Box<isize> = f(); }
+    thread::spawn(move|| g() ).join().unwrap_err();
+}
+
+pub fn main() {
+    test_break();
+    test_cont();
+    test_ret();
+    test_panic();
+    test_panic_indirect();
+}
index 3991c44f2edce620e2d0bcef0002363389506837..e52728f3781f8882f431b2bc3a990ad4a29c0067 100644 (file)
@@ -4,12 +4,6 @@ error[E0412]: cannot find type `Nonexistent` in this scope
 LL | impl Drop for Nonexistent {
    |               ^^^^^^^^^^^ not found in this scope
 
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
-  --> $DIR/drop-on-non-struct.rs:1:19
-   |
-LL | impl<'a> Drop for &'a mut isize {
-   |                   ^^^^^^^^^^^^^ must be a struct, enum, or union
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/drop-on-non-struct.rs:1:1
    |
@@ -21,6 +15,12 @@ LL | impl<'a> Drop for &'a mut isize {
    |
    = note: define and implement a trait or new type instead
 
+error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+  --> $DIR/drop-on-non-struct.rs:1:19
+   |
+LL | impl<'a> Drop for &'a mut isize {
+   |                   ^^^^^^^^^^^^^ must be a struct, enum, or union
+
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0117, E0120, E0412.
diff --git a/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs b/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs
new file mode 100644 (file)
index 0000000..23fd86a
--- /dev/null
@@ -0,0 +1,46 @@
+// run-pass
+
+// Demonstrate the use of the unguarded escape hatch with a type param in negative position
+// to assert that destructor will not access any dead data.
+//
+// Compare with ui/span/issue28498-reject-lifetime-param.rs
+
+// Demonstrate that a type param in negative position causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
+
+#![feature(dropck_eyepatch)]
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+
+unsafe impl<#[may_dangle] T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `may_dangle` is sound, because destructor never passes a `self.1`
+        // to the callback (in `self.2`) despite having it available.
+        println!("Dropping Foo({}, _)", self.0);
+    }
+}
+
+fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped, Box::new(callback));
+    foo1 = Foo(1, &first_dropped, Box::new(callback));
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/ui/editions-crate-root-2015.rs b/src/test/ui/editions-crate-root-2015.rs
deleted file mode 100644 (file)
index 4c890e3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// edition:2015
-
-mod inner {
-    fn global_inner(_: ::nonexistant::Foo) {
-        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
-    }
-    fn crate_inner(_: crate::nonexistant::Foo) {
-        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
-    }
-
-    fn bare_global(_: ::nonexistant) {
-        //~^ ERROR cannot find type `nonexistant` in the crate root
-    }
-    fn bare_crate(_: crate::nonexistant) {
-        //~^ ERROR cannot find type `nonexistant` in the crate root
-    }
-}
-
-fn main() {
-
-}
diff --git a/src/test/ui/editions-crate-root-2015.stderr b/src/test/ui/editions-crate-root-2015.stderr
deleted file mode 100644 (file)
index f8d65fe..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
-  --> $DIR/editions-crate-root-2015.rs:4:26
-   |
-LL |     fn global_inner(_: ::nonexistant::Foo) {
-   |                          ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
-
-error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
-  --> $DIR/editions-crate-root-2015.rs:7:30
-   |
-LL |     fn crate_inner(_: crate::nonexistant::Foo) {
-   |                              ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
-
-error[E0412]: cannot find type `nonexistant` in the crate root
-  --> $DIR/editions-crate-root-2015.rs:11:25
-   |
-LL |     fn bare_global(_: ::nonexistant) {
-   |                         ^^^^^^^^^^^ not found in the crate root
-
-error[E0412]: cannot find type `nonexistant` in the crate root
-  --> $DIR/editions-crate-root-2015.rs:14:29
-   |
-LL |     fn bare_crate(_: crate::nonexistant) {
-   |                             ^^^^^^^^^^^ not found in the crate root
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0412, E0433.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/editions/epoch-gate-feature.rs b/src/test/ui/editions/epoch-gate-feature.rs
new file mode 100644 (file)
index 0000000..5f7feb5
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Checks if the correct registers are being used to pass arguments
+// when the sysv64 ABI is specified.
+
+#![feature(rust_2018_preview)]
+
+pub trait Foo {}
+
+// should compile without the dyn trait feature flag
+fn foo(x: &dyn Foo) {}
+
+pub fn main() {}
diff --git a/src/test/ui/enum-discriminant/issue-51582.rs b/src/test/ui/enum-discriminant/issue-51582.rs
new file mode 100644 (file)
index 0000000..40a70c6
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(core_intrinsics)]
+
+#[repr(i8)]
+pub enum Enum {
+    VariantA,
+    VariantB,
+}
+
+fn make_b() -> Enum { Enum::VariantB }
+
+fn main() {
+    assert_eq!(1, make_b() as i8);
+    assert_eq!(1, make_b() as u8);
+    assert_eq!(1, make_b() as i32);
+    assert_eq!(1, make_b() as u32);
+    assert_eq!(1, std::intrinsics::discriminant_value(&make_b()));
+}
diff --git a/src/test/ui/enum/issue-42747.rs b/src/test/ui/enum/issue-42747.rs
new file mode 100644 (file)
index 0000000..fec6587
--- /dev/null
@@ -0,0 +1,46 @@
+// run-pass
+macro_rules! fooN {
+    ($cur:ident $prev:ty) => {
+        #[allow(dead_code)]
+        enum $cur {
+            Empty,
+            First($prev),
+            Second($prev),
+            Third($prev),
+            Fourth($prev),
+        }
+    }
+}
+
+fooN!(Foo0 ());
+fooN!(Foo1 Foo0);
+fooN!(Foo2 Foo1);
+fooN!(Foo3 Foo2);
+fooN!(Foo4 Foo3);
+fooN!(Foo5 Foo4);
+fooN!(Foo6 Foo5);
+fooN!(Foo7 Foo6);
+fooN!(Foo8 Foo7);
+fooN!(Foo9 Foo8);
+fooN!(Foo10 Foo9);
+fooN!(Foo11 Foo10);
+fooN!(Foo12 Foo11);
+fooN!(Foo13 Foo12);
+fooN!(Foo14 Foo13);
+fooN!(Foo15 Foo14);
+fooN!(Foo16 Foo15);
+fooN!(Foo17 Foo16);
+fooN!(Foo18 Foo17);
+fooN!(Foo19 Foo18);
+fooN!(Foo20 Foo19);
+fooN!(Foo21 Foo20);
+fooN!(Foo22 Foo21);
+fooN!(Foo23 Foo22);
+fooN!(Foo24 Foo23);
+fooN!(Foo25 Foo24);
+fooN!(Foo26 Foo25);
+fooN!(Foo27 Foo26);
+
+fn main() {
+    let _foo = Foo27::Empty;
+}
diff --git a/src/test/ui/epoch-gate-feature.rs b/src/test/ui/epoch-gate-feature.rs
deleted file mode 100644 (file)
index 5f7feb5..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-#![allow(unused_variables)]
-// Checks if the correct registers are being used to pass arguments
-// when the sysv64 ABI is specified.
-
-#![feature(rust_2018_preview)]
-
-pub trait Foo {}
-
-// should compile without the dyn trait feature flag
-fn foo(x: &dyn Foo) {}
-
-pub fn main() {}
index b48a1d8e50d4de1c665b3a86fdad7f9abf29ef52..cdbafff2a202bbc70e098609b28cb58660aea48a 100644 (file)
@@ -1,9 +1,3 @@
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
-  --> $DIR/E0117.rs:1:15
-   |
-LL | impl Drop for u32 {}
-   |               ^^^ must be a struct, enum, or union
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/E0117.rs:1:1
    |
@@ -15,6 +9,12 @@ LL | impl Drop for u32 {}
    |
    = note: define and implement a trait or new type instead
 
+error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+  --> $DIR/E0117.rs:1:15
+   |
+LL | impl Drop for u32 {}
+   |               ^^^ must be a struct, enum, or union
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0117, E0120.
index bace046758112a497156a345758a7bfb1d3d1533..0f3d427ce11ac4fa430886ddd1333e1dada11ea3 100644 (file)
@@ -1,9 +1,3 @@
-type Foo = [u8; 256];
-
-impl Copy for Foo { }
-//~^ ERROR the trait `Copy` may not be implemented for this type
-//~| ERROR only traits defined in the current crate can be implemented for arbitrary types
-
 #[derive(Copy, Clone)]
 struct Bar;
 
index e4ad4ffb45fee6b2d0c1ca5fcc3da067d390aca2..57ae2647d339c7f5d880fe9b0611085994cdf636 100644 (file)
@@ -1,27 +1,9 @@
 error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/E0206.rs:3:15
-   |
-LL | impl Copy for Foo { }
-   |               ^^^ type is not a structure or enumeration
-
-error[E0206]: the trait `Copy` may not be implemented for this type
-  --> $DIR/E0206.rs:10:15
+  --> $DIR/E0206.rs:4:15
    |
 LL | impl Copy for &'static mut Bar { }
    |               ^^^^^^^^^^^^^^^^ type is not a structure or enumeration
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/E0206.rs:3:1
-   |
-LL | impl Copy for Foo { }
-   | ^^^^^^^^^^^^^^---
-   | |             |
-   | |             this is not defined in the current crate because arrays are always foreign
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0117, E0206.
-For more information about an error, try `rustc --explain E0117`.
+For more information about this error, try `rustc --explain E0206`.
index 7dbf93ada5e5b9a948379009ec9195959e489831..9149e4ce58e767990d7014ac7b359673757dbfe8 100644 (file)
@@ -7,6 +7,5 @@
 struct Q;
 
 impl<R> External for (Q, R) {} //~ ERROR only traits defined
-//~^ ERROR conflicting implementations of trait
 
 fn main() {}
index 6a1a502749a75eb1e58320688e8f369b15c60768..654073eec2602bb5542f68a90b08824b5b42596a 100644 (file)
@@ -1,13 +1,3 @@
-error[E0119]: conflicting implementations of trait `complex_impl_support::External` for type `(Q, complex_impl_support::M<'_, '_, '_, std::boxed::Box<_>, _, _>)`
-  --> $DIR/complex-impl.rs:9:1
-   |
-LL | impl<R> External for (Q, R) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `complex_impl_support`:
-           - impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box<U>, V, W>)
-             where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
-
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/complex-impl.rs:9:1
    |
@@ -19,7 +9,6 @@ LL | impl<R> External for (Q, R) {}
    |
    = note: define and implement a trait or new type instead
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0117, E0119.
-For more information about an error, try `rustc --explain E0117`.
+For more information about this error, try `rustc --explain E0117`.
index c31b212b25a0df00e64c20392ea267f145b9ab9b..5fb7e9a9913abb0dc17b1ba6f8c77ae4c5df489b 100644 (file)
@@ -3,6 +3,5 @@
 struct Foo;
 
 impl<Foo> Deref for Foo { } //~ ERROR must be used
-//~^ ERROR conflicting implementations
 
 fn main() {}
index 56e8e1eb5400242783f4c3d2fb35438adedbf48b..97b570bc7aca369af4125afb2c21ed08ac86549a 100644 (file)
@@ -1,13 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::ops::Deref` for type `&_`
-  --> $DIR/issue-28981.rs:5:1
-   |
-LL | impl<Foo> Deref for Foo { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<T> Deref for &T
-             where T: ?Sized;
-
 error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g., `MyStruct<Foo>`)
   --> $DIR/issue-28981.rs:5:6
    |
@@ -17,7 +7,6 @@ LL | impl<Foo> Deref for Foo { }
    = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0119, E0210.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/extern/issue-28324.mir.stderr b/src/test/ui/extern/issue-28324.mir.stderr
new file mode 100644 (file)
index 0000000..aff8bf7
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-28324.rs:8:24
+   |
+LL | pub static BAZ: u32 = *&error_message_count;
+   |                        ^^^^^^^^^^^^^^^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/extern/issue-28324.rs b/src/test/ui/extern/issue-28324.rs
new file mode 100644 (file)
index 0000000..fbe83e3
--- /dev/null
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+extern "C" {
+    static error_message_count: u32;
+}
+
+pub static BAZ: u32 = *&error_message_count;
+//~^ ERROR use of extern static is unsafe and requires
+
+fn main() {}
diff --git a/src/test/ui/extern/issue-28324.thir.stderr b/src/test/ui/extern/issue-28324.thir.stderr
new file mode 100644 (file)
index 0000000..c696c35
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-28324.rs:8:25
+   |
+LL | pub static BAZ: u32 = *&error_message_count;
+   |                         ^^^^^^^^^^^^^^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.rs b/src/test/ui/feature-gates/feature-gate-asm_const.rs
new file mode 100644 (file)
index 0000000..c152b54
--- /dev/null
@@ -0,0 +1,10 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("mov eax, {}", const 123);
+        //~^ ERROR const operands for inline assembly are unstable
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.stderr b/src/test/ui/feature-gates/feature-gate-asm_const.stderr
new file mode 100644 (file)
index 0000000..2851a9b
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: const operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_const.rs:7:29
+   |
+LL |         asm!("mov eax, {}", const 123);
+   |                             ^^^^^^^^^
+   |
+   = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+   = help: add `#![feature(asm_const)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.rs
new file mode 100644 (file)
index 0000000..53e2a4d
--- /dev/null
@@ -0,0 +1,21 @@
+// compile-flags: --target mips-unknown-linux-gnu
+// needs-llvm-components: mips
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+unsafe fn main() {
+    asm!("");
+    //~^ ERROR inline assembly is not stable yet on this architecture
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr b/src/test/ui/feature-gates/feature-gate-asm_experimental_arch.stderr
new file mode 100644 (file)
index 0000000..1b4188a
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: inline assembly is not stable yet on this architecture
+  --> $DIR/feature-gate-asm_experimental_arch.rs:19:5
+   |
+LL |     asm!("");
+   |     ^^^^^^^^
+   |
+   = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+   = help: add `#![feature(asm_experimental_arch)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.rs b/src/test/ui/feature-gates/feature-gate-asm_sym.rs
new file mode 100644 (file)
index 0000000..d89c7dd
--- /dev/null
@@ -0,0 +1,10 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("mov eax, {}", sym main);
+        //~^ ERROR sym operands for inline assembly are unstable
+    }
+}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr
new file mode 100644 (file)
index 0000000..99b61b8
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: sym operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_sym.rs:7:29
+   |
+LL |         asm!("mov eax, {}", sym main);
+   |                             ^^^^^^^^
+   |
+   = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+   = help: add `#![feature(asm_sym)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs b/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.rs
deleted file mode 100644 (file)
index 520c147..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#[derive(Debug)]
-struct Machine<S> {
-    state: S,
-    common_field1: &'static str,
-    common_field2: i32,
-}
-#[derive(Debug)]
-struct State1;
-#[derive(Debug, PartialEq)]
-struct State2;
-
-fn update_to_state2() {
-    let m1: Machine<State1> = Machine {
-        state: State1,
-        common_field1: "hello",
-        common_field2: 2,
-    };
-    let m2: Machine<State2> = Machine {
-        state: State2,
-        ..m1 //~ ERROR mismatched types
-    };
-    // FIXME: this should trigger feature gate
-    assert_eq!(State2, m2.state);
-}
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr b/src/test/ui/feature-gates/feature-gate-type_changing_struct_update.stderr
deleted file mode 100644 (file)
index 9934fe6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-type_changing_struct_update.rs:20:11
-   |
-LL |         ..m1
-   |           ^^ expected struct `State2`, found struct `State1`
-   |
-   = note: expected struct `Machine<State2>`
-              found struct `Machine<State1>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/for-loop-while/issue-51345.rs b/src/test/ui/for-loop-while/issue-51345.rs
new file mode 100644 (file)
index 0000000..15571e8
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+#![allow(unreachable_code)]
+
+fn main() {
+    let mut v = Vec::new();
+
+    loop { v.push(break) }
+}
diff --git a/src/test/ui/for-loop-while/long-while.rs b/src/test/ui/for-loop-while/long-while.rs
new file mode 100644 (file)
index 0000000..529cca7
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+#![allow(unused_variables)]
+
+pub fn main() {
+    let mut i: isize = 0;
+    while i < 1000000 {
+        i += 1;
+        let x = 3;
+    }
+}
diff --git a/src/test/ui/foreign/nil-decl-in-foreign.rs b/src/test/ui/foreign/nil-decl-in-foreign.rs
new file mode 100644 (file)
index 0000000..f3be948
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+
+#![allow(improper_ctypes)]
+#![allow(dead_code)]
+// Issue #901
+// pretty-expanded FIXME #23616
+
+mod libc {
+    extern "C" {
+        pub fn printf(x: ());
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-88595.rs b/src/test/ui/generic-associated-types/issue-88595.rs
new file mode 100644 (file)
index 0000000..e397390
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+fn main() {}
+
+trait A<'a> {
+    type B<'b>: Clone
+    // FIXME(generic_associated_types): Remove one of the below bounds
+    // https://github.com/rust-lang/rust/pull/90678#discussion_r744976085
+    where
+        'a: 'b, Self: 'a, Self: 'b;
+
+    fn a(&'a self) -> Self::B<'a>;
+}
+
+struct C;
+
+impl<'a> A<'a> for C {
+    type B<'b> = impl Clone;
+    //~^ ERROR: lifetime bound not satisfied
+    //~| ERROR: could not find defining uses
+
+    fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
+}
diff --git a/src/test/ui/generic-associated-types/issue-88595.stderr b/src/test/ui/generic-associated-types/issue-88595.stderr
new file mode 100644 (file)
index 0000000..1948f82
--- /dev/null
@@ -0,0 +1,40 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-88595.rs:19:5
+   |
+LL |     type B<'b> = impl Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+  --> $DIR/issue-88595.rs:18:6
+   |
+LL | impl<'a> A<'a> for C {
+   |      ^^
+note: but lifetime parameter must outlive the lifetime `'b` as defined here
+  --> $DIR/issue-88595.rs:19:12
+   |
+LL |     type B<'b> = impl Clone;
+   |            ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-88595.rs:23:23
+   |
+LL |     fn a(&'a self) -> Self::B<'a> {}
+   |                       ^^^^^^^^^^^
+   |
+note: lifetime used multiple times
+  --> $DIR/issue-88595.rs:18:6
+   |
+LL | impl<'a> A<'a> for C {
+   |      ^^
+LL |     type B<'b> = impl Clone;
+   |            ^^
+
+error: could not find defining uses
+  --> $DIR/issue-88595.rs:19:18
+   |
+LL |     type B<'b> = impl Clone;
+   |                  ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/generic-associated-types/issue-90014.rs b/src/test/ui/generic-associated-types/issue-90014.rs
new file mode 100644 (file)
index 0000000..f110b06
--- /dev/null
@@ -0,0 +1,22 @@
+// edition:2018
+
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+use std::future::Future;
+
+trait MakeFut {
+    type Fut<'a> where Self: 'a;
+    fn make_fut<'a>(&'a self) -> Self::Fut<'a>;
+}
+
+impl MakeFut for &'_ mut () {
+    type Fut<'a> = impl Future<Output = ()>;
+    //~^ ERROR: the type `&mut ()` does not fulfill the required lifetime
+
+    fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
+        async { () }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr
new file mode 100644 (file)
index 0000000..125d817
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0477]: the type `&mut ()` does not fulfill the required lifetime
+  --> $DIR/issue-90014.rs:14:5
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: type must outlive the lifetime `'a` as defined here
+  --> $DIR/issue-90014.rs:14:14
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |              ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/generics/issue-1112.rs b/src/test/ui/generics/issue-1112.rs
new file mode 100644 (file)
index 0000000..3ba7bb2
--- /dev/null
@@ -0,0 +1,37 @@
+// run-pass
+#![allow(dead_code)]
+// Issue #1112
+// Alignment of interior pointers to dynamic-size types
+
+
+struct X<T> {
+    a: T,
+    b: u8,
+    c: bool,
+    d: u8,
+    e: u16,
+    f: u8,
+    g: u8
+}
+
+pub fn main() {
+    let x: X<isize> = X {
+        a: 12345678,
+        b: 9,
+        c: true,
+        d: 10,
+        e: 11,
+        f: 12,
+        g: 13
+    };
+    bar(x);
+}
+
+fn bar<T>(x: X<T>) {
+    assert_eq!(x.b, 9);
+    assert_eq!(x.c, true);
+    assert_eq!(x.d, 10);
+    assert_eq!(x.e, 11);
+    assert_eq!(x.f, 12);
+    assert_eq!(x.g, 13);
+}
diff --git a/src/test/ui/generics/issue-333.rs b/src/test/ui/generics/issue-333.rs
new file mode 100644 (file)
index 0000000..0753aaa
--- /dev/null
@@ -0,0 +1,7 @@
+// run-pass
+
+fn quux<T>(x: T) -> T { let f = id::<T>; return f(x); }
+
+fn id<T>(x: T) -> T { return x; }
+
+pub fn main() { assert_eq!(quux(10), 10); }
diff --git a/src/test/ui/generics/issue-59508-1.rs b/src/test/ui/generics/issue-59508-1.rs
new file mode 100644 (file)
index 0000000..6376c42
--- /dev/null
@@ -0,0 +1,17 @@
+#![allow(dead_code)]
+#![feature(const_generics_defaults)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions mention that
+// consts come after types and lifetimes when the `const_generics_defaults` feature is enabled.
+// We cannot run rustfix on this test because of the above const generics warning.
+
+struct A;
+
+impl A {
+    pub fn do_things<T, 'a, 'b: 'a>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-59508-1.stderr b/src/test/ui/generics/issue-59508-1.stderr
new file mode 100644 (file)
index 0000000..df244f0
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-59508-1.rs:11:25
+   |
+LL |     pub fn do_things<T, 'a, 'b: 'a>() {
+   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generics/issue-59508.fixed b/src/test/ui/generics/issue-59508.fixed
new file mode 100644 (file)
index 0000000..b5c60a1
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<'a, 'b: 'a, T>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-59508.rs b/src/test/ui/generics/issue-59508.rs
new file mode 100644 (file)
index 0000000..0b39c5d
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+    pub fn do_things<T, 'a, 'b: 'a>() {
+    //~^ ERROR lifetime parameters must be declared prior to type parameters
+        println!("panic");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generics/issue-59508.stderr b/src/test/ui/generics/issue-59508.stderr
new file mode 100644 (file)
index 0000000..33e967c
--- /dev/null
@@ -0,0 +1,8 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/issue-59508.rs:10:25
+   |
+LL |     pub fn do_things<T, 'a, 'b: 'a>() {
+   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs
new file mode 100644 (file)
index 0000000..c63b154
--- /dev/null
@@ -0,0 +1,20 @@
+pub trait Trait<'a> {
+    type Item;
+}
+
+impl<'a> Trait<'a> for () {
+    type Item = ();
+}
+
+pub fn foo<T, F>(_: T, _: F)
+where
+    T: for<'a> Trait<'a>,
+    F: for<'a> FnMut(<T as Trait<'a>>::Item),
+{
+}
+
+fn main() {
+    foo((), drop)
+    //~^ ERROR type mismatch in function arguments
+    //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr b/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr
new file mode 100644 (file)
index 0000000..34893cd
--- /dev/null
@@ -0,0 +1,42 @@
+error[E0631]: type mismatch in function arguments
+  --> $DIR/issue-60283.rs:17:13
+   |
+LL |     foo((), drop)
+   |     ---     ^^^^
+   |     |       |
+   |     |       expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+   |     |       found signature of `fn(()) -> _`
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `foo`
+  --> $DIR/issue-60283.rs:12:16
+   |
+LL | pub fn foo<T, F>(_: T, _: F)
+   |        --- required by a bound in this
+...
+LL |     F: for<'a> FnMut(<T as Trait<'a>>::Item),
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+  --> $DIR/issue-60283.rs:17:13
+   |
+LL |     foo((), drop)
+   |     ---     ^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
+note: required by a bound in `std::mem::drop`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL | pub fn drop<T>(_x: T) {}
+   |             ^ required by this bound in `std::mem::drop`
+help: consider further restricting the associated type
+   |
+LL | fn main() where <() as Trait<'_>>::Item: Sized {
+   |           ++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hygiene/lambda-var-hygiene.rs b/src/test/ui/hygiene/lambda-var-hygiene.rs
new file mode 100644 (file)
index 0000000..bf06765
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+// shouldn't affect evaluation of $ex:
+macro_rules! bad_macro {
+    ($ex:expr) => ({(|_x| { $ex }) (9) })
+}
+
+fn takes_x(_x : isize) {
+    assert_eq!(bad_macro!(_x),8);
+}
+fn main() {
+    takes_x(8);
+}
index 6adc4e6b23968ed57e04443005c220aed915727d..a25c85faf4e352c86d5ef7584fbbb81899aaa999 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     foo::<str>("".to_string());
    |           ^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issue-49579.rs b/src/test/ui/impl-trait/issue-49579.rs
new file mode 100644 (file)
index 0000000..98de014
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+
+fn fibs(n: u32) -> impl Iterator<Item=u128> {
+    (0 .. n)
+    .scan((0, 1), |st, _| {
+        *st = (st.1, st.0 + st.1);
+        Some(*st)
+    })
+    .map(&|(f, _)| f)
+}
+
+fn main() {
+    println!("{:?}", fibs(10).collect::<Vec<_>>());
+}
diff --git a/src/test/ui/impl-trait/issue-49685.rs b/src/test/ui/impl-trait/issue-49685.rs
new file mode 100644 (file)
index 0000000..fb328d6
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+// Regression test for #49685: drop elaboration was not revealing the
+// value of `impl Trait` returns, leading to an ICE.
+
+fn main() {
+    let _ = Some(())
+        .into_iter()
+        .flat_map(|_| Some(()).into_iter().flat_map(func));
+}
+
+fn func(_: ()) -> impl Iterator<Item = ()> {
+    Some(()).into_iter().flat_map(|_| vec![])
+}
diff --git a/src/test/ui/impl-trait/issue-51185.rs b/src/test/ui/impl-trait/issue-51185.rs
new file mode 100644 (file)
index 0000000..52a2b25
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+fn foo() -> impl Into<for<'a> fn(&'a ())> {
+    (|_| {}) as for<'a> fn(&'a ())
+}
+
+fn main() {
+    foo().into()(&());
+}
index 6800b37b5b175aaaee409116c67c9acefa9a4848..90c252537ef82b1b72f94e5fbc0a3fa3f3f9ec05 100644 (file)
@@ -3,6 +3,9 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     foo::<String>('a');
    |           ^^^^^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index db66d461095993f8fb9f5b3ad9a5c711dcadb30f..84b98f71f4f0caefea1347220c2dec8ea761d96b 100644 (file)
@@ -5,6 +5,9 @@ LL |     evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
    |                        ^^^^^^^^^  ^^^^^^^^^^^^^ explicit generic argument not allowed
    |                        |
    |                        explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
index 4605e76ac96d28a44cb50f3563daee0b2be0d873..35fb42d6213226918f687979944f6812db7d6278 100644 (file)
@@ -235,6 +235,7 @@ impl <T = impl Debug> T {}
 //~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
 //~| WARNING this was previously accepted by the compiler but is being phased out
 //~| ERROR `impl Trait` not allowed outside of function and method return types
+//~| ERROR no nominal type found
 
 // Disallowed
 fn in_method_generic_param_default<T = impl Debug>(_: T) {}
index 7f11d30dbaa5faafe272cfcbf75da31e42a04b37..236cf449e85fa5050893e64709a4a507ec310fc0 100644 (file)
@@ -272,19 +272,19 @@ LL | impl <T = impl Debug> T {}
    |           ^^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:240:40
+  --> $DIR/where-allowed.rs:241:40
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                        ^^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:246:29
+  --> $DIR/where-allowed.rs:247:29
    |
 LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
-  --> $DIR/where-allowed.rs:248:46
+  --> $DIR/where-allowed.rs:249:46
    |
 LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |                                              ^^^^^^^^^
@@ -300,7 +300,7 @@ LL | impl <T = impl Debug> T {}
    = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:240:36
+  --> $DIR/where-allowed.rs:241:36
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                    ^
@@ -308,7 +308,15 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    = 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 #36887 <https://github.com/rust-lang/rust/issues/36887>
 
-error: aborting due to 48 previous errors
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/where-allowed.rs:234:23
+   |
+LL | impl <T = impl Debug> T {}
+   |                       ^ impl requires a nominal type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to 49 previous errors
 
-Some errors have detailed explanations: E0562, E0658, E0666.
-For more information about an error, try `rustc --explain E0562`.
+Some errors have detailed explanations: E0118, E0562, E0658, E0666.
+For more information about an error, try `rustc --explain E0118`.
diff --git a/src/test/ui/in-band-lifetimes.rs b/src/test/ui/in-band-lifetimes.rs
deleted file mode 100644 (file)
index 9b2e1fe..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// run-pass
-
-#![allow(warnings)]
-#![feature(in_band_lifetimes)]
-
-fn foo(x: &'x u8) -> &'x u8 { x }
-fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x }
-
-fn check_in_band_can_be_late_bound() {
-    let _: for<'x> fn(&'x u8, &u8) -> &'x u8 = foo2;
-}
-
-struct ForInherentNoParams;
-
-impl ForInherentNoParams {
-    fn foo(x: &'a u32, y: &u32) -> &'a u32 { x }
-}
-
-struct X<'a>(&'a u8);
-
-impl<'a> X<'a> {
-    fn inner(&self) -> &'a u8 {
-        self.0
-    }
-
-    fn same_lifetime_as_parameter(&mut self, x: &'a u8) {
-        self.0 = x;
-    }
-}
-
-impl X<'b> {
-    fn inner_2(&self) -> &'b u8 {
-        self.0
-    }
-
-    fn reference_already_introduced_in_band_from_method_with_explicit_binders<'a>(
-        &'b self, x: &'a u32
-    ) {}
-}
-
-struct Y<T>(T);
-
-impl Y<&'a u8> {
-    fn inner(&self) -> &'a u8 {
-        self.0
-    }
-}
-
-trait MyTrait<'a> {
-    fn my_lifetime(&self) -> &'a u8;
-    fn any_lifetime() -> &'b u8;
-    fn borrowed_lifetime(&'b self) -> &'b u8;
-    fn default_impl(&self, x: &'b u32, y: &u32) -> &'b u32 { x }
-    fn in_band_def_explicit_impl(&self, x: &'b u8);
-}
-
-impl MyTrait<'a> for Y<&'a u8> {
-    fn my_lifetime(&self) -> &'a u8 { self.0 }
-    fn any_lifetime() -> &'b u8 { &0 }
-    fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
-    fn in_band_def_explicit_impl<'b>(&self, x: &'b u8) {}
-}
-
-fn test_hrtb_defined_lifetime_where<F>(_: F) where for<'a> F: Fn(&'a u8) {}
-fn test_hrtb_defined_lifetime_polytraitref<F>(_: F) where F: for<'a> Fn(&'a u8) {}
-
-fn reference_in_band_from_locals(x: &'test u32) -> &'test u32 {
-    let y: &'test u32 = x;
-    y
-}
-
-fn in_generics_in_band<T: MyTrait<'a>>(x: &T) {}
-fn where_clause_in_band<T>(x: &T) where T: MyTrait<'a> {}
-fn impl_trait_in_band(x: &impl MyTrait<'a>) {}
-
-// Tests around using in-band lifetimes within existential traits.
-
-trait FunkyTrait<'a> { }
-impl<'a, T> FunkyTrait<'a> for T { }
-fn ret_pos_impl_trait_in_band_outlives(x: &'a u32) -> impl ::std::fmt::Debug + 'a {
-    x
-}
-fn ret_pos_impl_trait_in_band_param(x: &'a u32) -> impl FunkyTrait<'a> {
-    x
-}
-fn ret_pos_impl_trait_in_band_param_static(x: &'a u32) -> impl FunkyTrait<'static> + 'a {
-    x
-}
-fn ret_pos_impl_trait_in_band_param_outlives(x: &'a u32) -> impl FunkyTrait<'a> + 'a {
-    x
-}
-fn ret_pos_impl_trait_in_band_higher_ranked(x: &'a u32) -> impl for<'b> FunkyTrait<'b> + 'a {
-    x
-}
-
-fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/in-band-lifetimes.rs b/src/test/ui/in-band-lifetimes/in-band-lifetimes.rs
new file mode 100644 (file)
index 0000000..9b2e1fe
--- /dev/null
@@ -0,0 +1,96 @@
+// run-pass
+
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo(x: &'x u8) -> &'x u8 { x }
+fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x }
+
+fn check_in_band_can_be_late_bound() {
+    let _: for<'x> fn(&'x u8, &u8) -> &'x u8 = foo2;
+}
+
+struct ForInherentNoParams;
+
+impl ForInherentNoParams {
+    fn foo(x: &'a u32, y: &u32) -> &'a u32 { x }
+}
+
+struct X<'a>(&'a u8);
+
+impl<'a> X<'a> {
+    fn inner(&self) -> &'a u8 {
+        self.0
+    }
+
+    fn same_lifetime_as_parameter(&mut self, x: &'a u8) {
+        self.0 = x;
+    }
+}
+
+impl X<'b> {
+    fn inner_2(&self) -> &'b u8 {
+        self.0
+    }
+
+    fn reference_already_introduced_in_band_from_method_with_explicit_binders<'a>(
+        &'b self, x: &'a u32
+    ) {}
+}
+
+struct Y<T>(T);
+
+impl Y<&'a u8> {
+    fn inner(&self) -> &'a u8 {
+        self.0
+    }
+}
+
+trait MyTrait<'a> {
+    fn my_lifetime(&self) -> &'a u8;
+    fn any_lifetime() -> &'b u8;
+    fn borrowed_lifetime(&'b self) -> &'b u8;
+    fn default_impl(&self, x: &'b u32, y: &u32) -> &'b u32 { x }
+    fn in_band_def_explicit_impl(&self, x: &'b u8);
+}
+
+impl MyTrait<'a> for Y<&'a u8> {
+    fn my_lifetime(&self) -> &'a u8 { self.0 }
+    fn any_lifetime() -> &'b u8 { &0 }
+    fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+    fn in_band_def_explicit_impl<'b>(&self, x: &'b u8) {}
+}
+
+fn test_hrtb_defined_lifetime_where<F>(_: F) where for<'a> F: Fn(&'a u8) {}
+fn test_hrtb_defined_lifetime_polytraitref<F>(_: F) where F: for<'a> Fn(&'a u8) {}
+
+fn reference_in_band_from_locals(x: &'test u32) -> &'test u32 {
+    let y: &'test u32 = x;
+    y
+}
+
+fn in_generics_in_band<T: MyTrait<'a>>(x: &T) {}
+fn where_clause_in_band<T>(x: &T) where T: MyTrait<'a> {}
+fn impl_trait_in_band(x: &impl MyTrait<'a>) {}
+
+// Tests around using in-band lifetimes within existential traits.
+
+trait FunkyTrait<'a> { }
+impl<'a, T> FunkyTrait<'a> for T { }
+fn ret_pos_impl_trait_in_band_outlives(x: &'a u32) -> impl ::std::fmt::Debug + 'a {
+    x
+}
+fn ret_pos_impl_trait_in_band_param(x: &'a u32) -> impl FunkyTrait<'a> {
+    x
+}
+fn ret_pos_impl_trait_in_band_param_static(x: &'a u32) -> impl FunkyTrait<'static> + 'a {
+    x
+}
+fn ret_pos_impl_trait_in_band_param_outlives(x: &'a u32) -> impl FunkyTrait<'a> + 'a {
+    x
+}
+fn ret_pos_impl_trait_in_band_higher_ranked(x: &'a u32) -> impl for<'b> FunkyTrait<'b> + 'a {
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/inference/lub-glb-with-unbound-infer-var.rs b/src/test/ui/inference/lub-glb-with-unbound-infer-var.rs
new file mode 100644 (file)
index 0000000..c9e1170
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+// Test for a specific corner case: when we compute the LUB of two fn
+// types and their parameters have unbound variables. In that case, we
+// wind up relating those two variables. This was causing an ICE in an
+// in-progress PR.
+
+fn main() {
+    let a_f: fn(_) = |_| ();
+    let b_f: fn(_) = |_| ();
+    let c_f = match 22 {
+        0 => a_f,
+        _ => b_f,
+    };
+    c_f(4);
+}
diff --git a/src/test/ui/inline-const/const-expr-inference.rs b/src/test/ui/inline-const/const-expr-inference.rs
new file mode 100644 (file)
index 0000000..6aa2a2f
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(inline_const)]
+#![allow(incomplete_features)]
+
+pub fn todo<T>() -> T {
+    const { todo!() }
+}
+
+fn main() {
+    let _: usize = const { 0 };
+}
diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.rs b/src/test/ui/inline-const/const-expr-lifetime-err.rs
new file mode 100644 (file)
index 0000000..e56cbc9
--- /dev/null
@@ -0,0 +1,30 @@
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+impl<'a> InvariantRef<'a, ()> {
+    pub const NEW: Self = InvariantRef::new(&());
+}
+
+fn equate<T>(x: T, y: T){}
+
+fn foo<'a>() {
+    let y = ();
+    equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
+    //~^ ERROR `y` does not live long enough [E0597]
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/inline-const/const-expr-lifetime-err.stderr b/src/test/ui/inline-const/const-expr-lifetime-err.stderr
new file mode 100644 (file)
index 0000000..30ecd33
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0597]: `y` does not live long enough
+  --> $DIR/const-expr-lifetime-err.rs:24:30
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let y = ();
+LL |     equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
+   |            ------------------^^-
+   |            |                 |
+   |            |                 borrowed value does not live long enough
+   |            argument requires that `y` is borrowed for `'a`
+LL |
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/inline-const/const-expr-lifetime.rs b/src/test/ui/inline-const/const-expr-lifetime.rs
new file mode 100644 (file)
index 0000000..f622f2c
--- /dev/null
@@ -0,0 +1,36 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
+fn issue_78174() {
+    let foo = const { "foo" };
+    assert_eq!(foo, "foo");
+}
+
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+fn get_invariant_ref<'a>() -> InvariantRef<'a, ()> {
+    const { InvariantRef::<'a, ()>::new(&()) }
+}
+
+fn get_invariant_ref2<'a>() -> InvariantRef<'a, ()> {
+    // Try some type inference
+    const { InvariantRef::new(&()) }
+}
+
+fn main() {
+    issue_78174();
+    get_invariant_ref();
+    get_invariant_ref2();
+}
diff --git a/src/test/ui/inline-const/const-match-pat-inference.rs b/src/test/ui/inline-const/const-match-pat-inference.rs
new file mode 100644 (file)
index 0000000..61188ed
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(inline_const)]
+#![allow(incomplete_features)]
+
+fn main() {
+    match 1u64 {
+        0 => (),
+        const { 0 + 1 } => (),
+        const { 2 - 1 } ..= const { u64::MAX } => (),
+    }
+}
diff --git a/src/test/ui/inline-const/const-match-pat-lifetime-err.rs b/src/test/ui/inline-const/const-match-pat-lifetime-err.rs
new file mode 100644 (file)
index 0000000..bc5aa24
--- /dev/null
@@ -0,0 +1,34 @@
+// ignore-test
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+impl<'a> InvariantRef<'a, ()> {
+    pub const NEW: Self = InvariantRef::new(&());
+}
+
+fn match_invariant_ref<'a>() {
+    let y = ();
+    match InvariantRef::new(&y) {
+    //~^ ERROR `y` does not live long enough [E0597]
+        // FIXME(nbdd0121): This should give the same error as `InvariantRef::<'a>::NEW` (without
+        // const block)
+        const { InvariantRef::<'a>::NEW } => (),
+    }
+}
+
+fn main() {
+    match_invariant_ref();
+}
diff --git a/src/test/ui/inline-const/const-match-pat-lifetime.rs b/src/test/ui/inline-const/const-match-pat-lifetime.rs
new file mode 100644 (file)
index 0000000..3d986f0
--- /dev/null
@@ -0,0 +1,36 @@
+// run-pass
+
+#![allow(incomplete_features)]
+#![feature(const_mut_refs)]
+#![feature(inline_const)]
+
+use std::marker::PhantomData;
+
+// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid"
+fn issue_78174() {
+    match "foo" {
+        const { concat!("fo", "o") } => (),
+        _ => unreachable!(),
+    }
+}
+
+#[derive(PartialEq, Eq)]
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a, T: ?Sized> InvariantRef<'a, T> {
+    pub const fn new(r: &'a T) -> Self {
+        InvariantRef(r, PhantomData)
+    }
+}
+
+fn match_invariant_ref<'a>() {
+    match const { InvariantRef::<'a, _>::new(&()) } {
+        const { InvariantRef::<'a, ()>::new(&()) } => {
+        }
+    }
+}
+
+fn main() {
+    issue_78174();
+    match_invariant_ref();
+}
index 5a27ea8783a2f3b149f23057929ff84c75b8d8cc..6007eba8c0906a2f9307ee7887ad7cbaab0f3e90 100644 (file)
@@ -15,6 +15,7 @@ mod rusti {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
diff --git a/src/test/ui/issues/auxiliary/issue-19163.rs b/src/test/ui/issues/auxiliary/issue-19163.rs
deleted file mode 100644 (file)
index 0c0d9e4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![crate_type = "lib"]
-
-#[macro_export]
-macro_rules! mywrite {
-    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
-}
diff --git a/src/test/ui/issues/auxiliary/issue-39823.rs b/src/test/ui/issues/auxiliary/issue-39823.rs
deleted file mode 100644 (file)
index 3af9c68..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#![crate_type="rlib"]
-
-#[derive(Debug, PartialEq)]
-pub struct RemoteC(pub u32);
-
-#[derive(Debug, PartialEq)]
-pub struct RemoteG<T>(pub T);
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs b/src/test/ui/issues/auxiliary/xcrate-issue-43189-a.rs
deleted file mode 100644 (file)
index 9ab570f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#![crate_type="lib"]
-
-
-pub trait A {
-    fn a(&self) {}
-}
-impl A for () {}
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs b/src/test/ui/issues/auxiliary/xcrate-issue-43189-b.rs
deleted file mode 100644 (file)
index 31dfb05..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type="lib"]
-
-pub extern crate xcrate_issue_43189_a;
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs b/src/test/ui/issues/auxiliary/xcrate-issue-46112-rexport-core.rs
deleted file mode 100644 (file)
index 2b517b5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type="lib"]
-
-pub extern crate core;
diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs b/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs
deleted file mode 100644 (file)
index 88a0405..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// edition:2018
-#![crate_type="lib"]
-#![crate_name="xcrate_issue_61711_b"]
-pub struct Struct;
-pub use crate as alias;
diff --git a/src/test/ui/issues/issue-10398.rs b/src/test/ui/issues/issue-10398.rs
deleted file mode 100644 (file)
index 0405b2d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(box_syntax)]
-
-fn main() {
-    let x: Box<_> = box 1;
-    let f = move|| {
-        let _a = x;
-        drop(x);
-        //~^ ERROR: use of moved value: `x`
-    };
-    f();
-}
diff --git a/src/test/ui/issues/issue-10398.stderr b/src/test/ui/issues/issue-10398.stderr
deleted file mode 100644 (file)
index 8d9faf3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0382]: use of moved value: `x`
-  --> $DIR/issue-10398.rs:7:14
-   |
-LL |         let _a = x;
-   |                  - value moved here
-LL |         drop(x);
-   |              ^ value used here after move
-   |
-   = note: move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/issues/issue-1112.rs b/src/test/ui/issues/issue-1112.rs
deleted file mode 100644 (file)
index 3ba7bb2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-// Issue #1112
-// Alignment of interior pointers to dynamic-size types
-
-
-struct X<T> {
-    a: T,
-    b: u8,
-    c: bool,
-    d: u8,
-    e: u16,
-    f: u8,
-    g: u8
-}
-
-pub fn main() {
-    let x: X<isize> = X {
-        a: 12345678,
-        b: 9,
-        c: true,
-        d: 10,
-        e: 11,
-        f: 12,
-        g: 13
-    };
-    bar(x);
-}
-
-fn bar<T>(x: X<T>) {
-    assert_eq!(x.b, 9);
-    assert_eq!(x.c, true);
-    assert_eq!(x.d, 10);
-    assert_eq!(x.e, 11);
-    assert_eq!(x.f, 12);
-    assert_eq!(x.g, 13);
-}
diff --git a/src/test/ui/issues/issue-11577.rs b/src/test/ui/issues/issue-11577.rs
deleted file mode 100644 (file)
index 70177c5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-// Destructuring struct variants would ICE where regular structs wouldn't
-
-enum Foo {
-    VBar { num: isize }
-}
-
-struct SBar { num: isize }
-
-pub fn main() {
-    let vbar = Foo::VBar { num: 1 };
-    let Foo::VBar { num } = vbar;
-    assert_eq!(num, 1);
-
-    let sbar = SBar { num: 2 };
-    let SBar { num } = sbar;
-    assert_eq!(num, 2);
-}
diff --git a/src/test/ui/issues/issue-11940.rs b/src/test/ui/issues/issue-11940.rs
deleted file mode 100644 (file)
index 6815c87..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-
-const TEST_STR: &'static str = "abcd";
-
-fn main() {
-    let s = "abcd";
-    match s {
-        TEST_STR => (),
-        _ => unreachable!()
-    }
-}
diff --git a/src/test/ui/issues/issue-12796.rs b/src/test/ui/issues/issue-12796.rs
deleted file mode 100644 (file)
index 942d6b9..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-trait Trait {
-    fn outer(&self) {
-        fn inner(_: &Self) {
-            //~^ ERROR can't use generic parameters from outer function
-        }
-    }
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-12796.stderr b/src/test/ui/issues/issue-12796.stderr
deleted file mode 100644 (file)
index a01fd2d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-12796.rs:3:22
-   |
-LL |         fn inner(_: &Self) {
-   |                      ^^^^
-   |                      |
-   |                      use of generic parameter from outer function
-   |                      can't use `Self` here
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-13483.rs b/src/test/ui/issues/issue-13483.rs
deleted file mode 100644 (file)
index a2fd926..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-fn main() {
-    if true {
-    } else if { //~ ERROR missing condition
-    //~^ ERROR mismatched types
-    } else {
-    }
-}
-
-fn foo() {
-    if true {
-    } else if { //~ ERROR missing condition
-    //~^ ERROR mismatched types
-    }
-    bar();
-}
-
-fn bar() {}
diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr
deleted file mode 100644 (file)
index 5fd05b1..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error: missing condition for `if` expression
-  --> $DIR/issue-13483.rs:3:14
-   |
-LL |     } else if {
-   |              ^ expected if condition here
-
-error: missing condition for `if` expression
-  --> $DIR/issue-13483.rs:11:14
-   |
-LL |     } else if {
-   |              ^ expected if condition here
-
-error[E0308]: mismatched types
-  --> $DIR/issue-13483.rs:3:15
-   |
-LL |       } else if {
-   |  _______________^
-LL | |
-LL | |     } else {
-   | |_____^ expected `bool`, found `()`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-13483.rs:11:15
-   |
-LL |       } else if {
-   |  _______________^
-LL | |
-LL | |     }
-   | |_____^ expected `bool`, found `()`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-13902.rs b/src/test/ui/issues/issue-13902.rs
deleted file mode 100644 (file)
index 1afde0e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
-const JSVAL_TYPE_INT32: u8 = 0x01;
-const JSVAL_TYPE_UNDEFINED: u8 = 0x02;
-#[repr(u32)]
-enum ValueTag {
-    JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32),
-    JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32),
-}
-
-fn main() {
-    let _ = ValueTag::JSVAL_TAG_INT32;
-}
diff --git a/src/test/ui/issues/issue-14227.mir.stderr b/src/test/ui/issues/issue-14227.mir.stderr
deleted file mode 100644 (file)
index 8e7a251..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-14227.rs:7:21
-   |
-LL | static CRASH: u32 = symbol;
-   |                     ^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-14227.rs b/src/test/ui/issues/issue-14227.rs
deleted file mode 100644 (file)
index 5f866ec..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-extern "C" {
-    pub static symbol: u32;
-}
-static CRASH: u32 = symbol;
-//~^ ERROR use of extern static is unsafe and requires
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-14227.thir.stderr b/src/test/ui/issues/issue-14227.thir.stderr
deleted file mode 100644 (file)
index 8e7a251..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-14227.rs:7:21
-   |
-LL | static CRASH: u32 = symbol;
-   |                     ^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-14456.rs b/src/test/ui/issues/issue-14456.rs
deleted file mode 100644 (file)
index 52a56eb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// run-pass
-#![allow(unused_mut)]
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-use std::env;
-use std::io::prelude::*;
-use std::io;
-use std::process::{Command, Stdio};
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    if args.len() > 1 && args[1] == "child" {
-        return child()
-    }
-
-    test();
-}
-
-fn child() {
-    writeln!(&mut io::stdout(), "foo").unwrap();
-    writeln!(&mut io::stderr(), "bar").unwrap();
-    let mut stdin = io::stdin();
-    let mut s = String::new();
-    stdin.lock().read_line(&mut s).unwrap();
-    assert_eq!(s.len(), 0);
-}
-
-fn test() {
-    let args: Vec<String> = env::args().collect();
-    let mut p = Command::new(&args[0]).arg("child")
-                                     .stdin(Stdio::piped())
-                                     .stdout(Stdio::piped())
-                                     .stderr(Stdio::piped())
-                                     .spawn().unwrap();
-    assert!(p.wait().unwrap().success());
-}
diff --git a/src/test/ui/issues/issue-14589.rs b/src/test/ui/issues/issue-14589.rs
deleted file mode 100644 (file)
index 5d8aab2..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-// All 3 expressions should work in that the argument gets
-// coerced to a trait object
-
-// pretty-expanded FIXME #23616
-
-fn main() {
-    send::<Box<dyn Foo>>(Box::new(Output(0)));
-    Test::<Box<dyn Foo>>::foo(Box::new(Output(0)));
-    Test::<Box<dyn Foo>>::new().send(Box::new(Output(0)));
-}
-
-fn send<T>(_: T) {}
-
-struct Test<T> { marker: std::marker::PhantomData<T> }
-impl<T> Test<T> {
-    fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } }
-    fn foo(_: T) {}
-    fn send(&self, _: T) {}
-}
-
-trait Foo { fn dummy(&self) { }}
-struct Output(isize);
-impl Foo for Output {}
diff --git a/src/test/ui/issues/issue-14837.rs b/src/test/ui/issues/issue-14837.rs
deleted file mode 100644 (file)
index a83bc41..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// check-pass
-// pretty-expanded FIXME #23616
-
-#[deny(dead_code)]
-pub enum Foo {
-    Bar {
-        baz: isize
-    }
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-15080.rs b/src/test/ui/issues/issue-15080.rs
deleted file mode 100644 (file)
index 4dd6981..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-
-fn main() {
-    let mut x: &[_] = &[1, 2, 3, 4];
-
-    let mut result = vec![];
-    loop {
-        x = match *x {
-            [1, n, 3, ref rest @ ..] => {
-                result.push(n);
-                rest
-            }
-            [n, ref rest @ ..] => {
-                result.push(n);
-                rest
-            }
-            [] =>
-                break
-        }
-    }
-    assert_eq!(result, [2, 4]);
-}
diff --git a/src/test/ui/issues/issue-16098.rs b/src/test/ui/issues/issue-16098.rs
deleted file mode 100644 (file)
index 00acc20..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-macro_rules! prob1 {
-    (0) => {
-        0
-    };
-    ($n:expr) => {
-        if ($n % 3 == 0) || ($n % 5 == 0) {
-            $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding `prob1!`
-        } else {
-            prob1!($n - 1);
-        }
-    };
-}
-
-fn main() {
-    println!("Problem 1: {}", prob1!(1000));
-}
diff --git a/src/test/ui/issues/issue-16098.stderr b/src/test/ui/issues/issue-16098.stderr
deleted file mode 100644 (file)
index 6428021..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: recursion limit reached while expanding `prob1!`
-  --> $DIR/issue-16098.rs:7:18
-   |
-LL |             $n + prob1!($n - 1);
-   |                  ^^^^^^^^^^^^^^
-...
-LL |     println!("Problem 1: {}", prob1!(1000));
-   |                               ------------ in this macro invocation
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`)
-   = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-16272.rs b/src/test/ui/issues/issue-16272.rs
deleted file mode 100644 (file)
index 5cf3fd9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-use std::process::Command;
-use std::env;
-
-fn main() {
-    let len = env::args().len();
-
-    if len == 1 {
-        test();
-    } else {
-        assert_eq!(len, 3);
-    }
-}
-
-fn test() {
-    let status = Command::new(&env::current_exe().unwrap())
-                         .arg("foo").arg("")
-                         .status().unwrap();
-    assert!(status.success());
-}
diff --git a/src/test/ui/issues/issue-17074.rs b/src/test/ui/issues/issue-17074.rs
deleted file mode 100644 (file)
index 0ed8113..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-
-static X2: u64 = !0 as u16 as u64;
-static Y2: u64 = !0 as u32 as u64;
-const X: u64 = !0 as u16 as u64;
-const Y: u64 = !0 as u32 as u64;
-
-fn main() {
-    assert_eq!(match 1 {
-        X => unreachable!(),
-        Y => unreachable!(),
-        _ => 1
-    }, 1);
-}
diff --git a/src/test/ui/issues/issue-18060.rs b/src/test/ui/issues/issue-18060.rs
deleted file mode 100644 (file)
index b5f3d0f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-// Regression test for #18060: match arms were matching in the wrong order.
-
-fn main() {
-    assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
-    assert_eq!(2, match (1, 3) {                  (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
-    assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 });
-}
diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/issues/issue-18294.rs
deleted file mode 100644 (file)
index 77355f0..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    const X: u32 = 1;
-    const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
-    println!("{}", Y);
-}
diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr
deleted file mode 100644 (file)
index e0cbd2a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: pointers cannot be cast to integers during const eval
-  --> $DIR/issue-18294.rs:3:31
-   |
-LL |     const Y: usize = unsafe { &X as *const u32 as usize };
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: at compile-time, pointers do not have an integer value
-   = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-18652.rs b/src/test/ui/issues/issue-18652.rs
deleted file mode 100644 (file)
index 59aa015..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// run-pass
-// Tests multiple free variables being passed by value into an unboxed
-// once closure as an optimization by codegen.  This used to hit an
-// incorrect assert.
-
-fn main() {
-    let x = 2u8;
-    let y = 3u8;
-    assert_eq!((move || x + y)(), 5);
-}
diff --git a/src/test/ui/issues/issue-19163.rs b/src/test/ui/issues/issue-19163.rs
deleted file mode 100644 (file)
index d98c591..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// aux-build:issue-19163.rs
-
-#[macro_use] extern crate issue_19163;
-
-use std::io::Write;
-
-fn main() {
-    let mut v = vec![];
-    mywrite!(&v, "Hello world");
-    //~^ ERROR cannot borrow data in a `&` reference as mutable
-}
diff --git a/src/test/ui/issues/issue-19163.stderr b/src/test/ui/issues/issue-19163.stderr
deleted file mode 100644 (file)
index ae1ae14..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/issue-19163.rs:9:5
-   |
-LL |     mywrite!(&v, "Hello world");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = note: this error originates in the macro `mywrite` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/issues/issue-19358.rs b/src/test/ui/issues/issue-19358.rs
deleted file mode 100644 (file)
index 3970a41..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-
-trait Trait { fn dummy(&self) { } }
-
-#[derive(Debug)]
-struct Foo<T: Trait> {
-    foo: T,
-}
-
-#[derive(Debug)]
-struct Bar<T> where T: Trait {
-    bar: T,
-}
-
-impl Trait for isize {}
-
-fn main() {
-    let a = Foo { foo: 12 };
-    let b = Bar { bar: 12 };
-    println!("{:?} {:?}", a, b);
-}
diff --git a/src/test/ui/issues/issue-19660.rs b/src/test/ui/issues/issue-19660.rs
deleted file mode 100644 (file)
index 400ac31..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// error-pattern: requires `copy` lang_item
-
-#![feature(lang_items, start, no_core)]
-#![no_core]
-
-#[lang = "sized"]
-trait Sized { }
-
-struct S;
-
-#[start]
-fn main(_: isize, _: *const *const u8) -> isize {
-    let _ = S;
-    0
-}
diff --git a/src/test/ui/issues/issue-19660.stderr b/src/test/ui/issues/issue-19660.stderr
deleted file mode 100644 (file)
index f5d903f..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-error: requires `copy` lang_item
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20091.rs b/src/test/ui/issues/issue-20091.rs
deleted file mode 100644 (file)
index 86cc79d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-#![allow(stable_features)]
-
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-#![feature(os)]
-
-#[cfg(unix)]
-fn main() {
-    use std::process::Command;
-    use std::env;
-    use std::os::unix::prelude::*;
-    use std::ffi::OsStr;
-
-    if env::args().len() == 1 {
-        assert!(Command::new(&env::current_exe().unwrap())
-                        .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
-                        .status().unwrap().success())
-    }
-}
-
-#[cfg(windows)]
-fn main() {}
diff --git a/src/test/ui/issues/issue-20616-4.rs b/src/test/ui/issues/issue-20616-4.rs
deleted file mode 100644 (file)
index a71f47c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-type Type_4<T> = Type_1_<'static,, T>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-4.stderr b/src/test/ui/issues/issue-20616-4.stderr
deleted file mode 100644 (file)
index 2b3b75f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-4.rs:16:34
-   |
-LL | type Type_4<T> = Type_1_<'static,, T>;
-   |                                  ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20616-5.rs b/src/test/ui/issues/issue-20616-5.rs
deleted file mode 100644 (file)
index b96d09d..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-type Type_5<'a> = Type_1_<'a, (),,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-5.stderr b/src/test/ui/issues/issue-20616-5.stderr
deleted file mode 100644 (file)
index 1ec1dbd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-5.rs:22:34
-   |
-LL | type Type_5<'a> = Type_1_<'a, (),,>;
-   |                                  ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20616-6.rs b/src/test/ui/issues/issue-20616-6.rs
deleted file mode 100644 (file)
index a2c45ec..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-type Type_6 = Type_5_<'a,,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-6.stderr b/src/test/ui/issues/issue-20616-6.stderr
deleted file mode 100644 (file)
index 7401abd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-6.rs:25:26
-   |
-LL | type Type_6 = Type_5_<'a,,>;
-   |                          ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20616-7.rs b/src/test/ui/issues/issue-20616-7.rs
deleted file mode 100644 (file)
index 67209c0..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-type Type_7 = Box<(),,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/issues/issue-20616-7.stderr b/src/test/ui/issues/issue-20616-7.stderr
deleted file mode 100644 (file)
index e2c3efe..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
-  --> $DIR/issue-20616-7.rs:28:22
-   |
-LL | type Type_7 = Box<(),,>;
-   |                      ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-20823.rs b/src/test/ui/issues/issue-20823.rs
deleted file mode 100644 (file)
index 9e209d5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// run-pass
-// compile-flags: --test
-
-#[test]
-pub fn foo() {}
diff --git a/src/test/ui/issues/issue-21356.rs b/src/test/ui/issues/issue-21356.rs
deleted file mode 100644 (file)
index ae62392..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![allow(unused_macros)]
-
-macro_rules! test { ($wrong:t_ty ..) => () }
-                  //~^ ERROR: invalid fragment specifier `t_ty`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-21356.stderr b/src/test/ui/issues/issue-21356.stderr
deleted file mode 100644 (file)
index 17014c6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: invalid fragment specifier `t_ty`
-  --> $DIR/issue-21356.rs:3:22
-   |
-LL | macro_rules! test { ($wrong:t_ty ..) => () }
-   |                      ^^^^^^^^^^^
-   |
-   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-21475.rs b/src/test/ui/issues/issue-21475.rs
deleted file mode 100644 (file)
index b028fca..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// run-pass
-#![allow(unused_imports, overlapping_range_endpoints)]
-// pretty-expanded FIXME #23616
-
-use m::{START, END};
-
-fn main() {
-    match 42 {
-        m::START..=m::END => {},
-        0..=m::END => {},
-        m::START..=59 => {},
-        _  => {},
-    }
-}
-
-mod m {
-  pub const START: u32 = 4;
-  pub const END:   u32 = 14;
-}
diff --git a/src/test/ui/issues/issue-21520.rs b/src/test/ui/issues/issue-21520.rs
deleted file mode 100644 (file)
index ab4ac72..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// check-pass
-#![allow(dead_code)]
-// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
-// not wind up propagating to `T`.
-
-// pretty-expanded FIXME #23616
-
-pub trait Foo {
-    type Bar;
-
-    fn foo(&self) -> Self;
-}
-
-pub struct Static<T:'static>(T);
-
-struct Bar<T:Foo>
-    where T::Bar : 'static
-{
-    x: Static<Option<T::Bar>>
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-22066.rs b/src/test/ui/issues/issue-22066.rs
deleted file mode 100644 (file)
index 8e8ba5d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// check-pass
-pub trait LineFormatter<'a> {
-    type Iter: Iterator<Item=&'a str> + 'a;
-    fn iter(&'a self, line: &'a str) -> Self::Iter;
-
-    fn dimensions(&'a self, line: &'a str) {
-        let iter: Self::Iter = self.iter(line);
-        <_ as IntoIterator>::into_iter(iter);
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-22463.rs b/src/test/ui/issues/issue-22463.rs
deleted file mode 100644 (file)
index fdf5a2f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-macro_rules! items {
-    () => {
-        type A = ();
-        fn a() {}
-    }
-}
-
-trait Foo {
-    type A;
-    fn a();
-}
-
-impl Foo for () {
-    items!();
-}
-
-fn main() {
-
-}
diff --git a/src/test/ui/issues/issue-22828.rs b/src/test/ui/issues/issue-22828.rs
deleted file mode 100644 (file)
index adf4dd6..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-// Test transitive analysis for associated types. Collected types
-// should be normalized and new obligations generated.
-
-// pretty-expanded FIXME #23616
-
-trait Foo {
-    type A;
-    fn foo(&self) {}
-}
-
-impl Foo for usize {
-    type A = usize;
-}
-
-struct Bar<T: Foo> { inner: T::A }
-
-fn is_send<T: Send>() {}
-
-fn main() {
-    is_send::<Bar<usize>>();
-}
diff --git a/src/test/ui/issues/issue-23458.rs b/src/test/ui/issues/issue-23458.rs
deleted file mode 100644 (file)
index d640828..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-// compile-flags: -Ccodegen-units=1
-// build-fail
-// only-x86_64
-
-fn main() {
-    unsafe {
-        llvm_asm!("int $3"); //~ ERROR too few operands for instruction
-                             //~| ERROR invalid operand in inline asm
-    }
-}
diff --git a/src/test/ui/issues/issue-23458.stderr b/src/test/ui/issues/issue-23458.stderr
deleted file mode 100644 (file)
index 69e458f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: invalid operand in inline asm: 'int $3'
-  --> $DIR/issue-23458.rs:9:9
-   |
-LL |         llvm_asm!("int $3");
-   |         ^
-
-error: too few operands for instruction
-  --> $DIR/issue-23458.rs:9:9
-   |
-LL |         llvm_asm!("int $3");
-   |         ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:2
-   |
-LL |     int 
-   |     ^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-23716.rs b/src/test/ui/issues/issue-23716.rs
deleted file mode 100644 (file)
index e9139c0..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-static foo: i32 = 0;
-
-fn bar(foo: i32) {}
-//~^ ERROR function parameters cannot shadow statics
-//~| cannot be named the same as a static
-
-mod submod {
-    pub static answer: i32 = 42;
-}
-
-use self::submod::answer;
-
-fn question(answer: i32) {}
-//~^ ERROR function parameters cannot shadow statics
-//~| cannot be named the same as a static
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-23716.stderr b/src/test/ui/issues/issue-23716.stderr
deleted file mode 100644 (file)
index e7bebfb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0530]: function parameters cannot shadow statics
-  --> $DIR/issue-23716.rs:3:8
-   |
-LL | static foo: i32 = 0;
-   | -------------------- the static `foo` is defined here
-LL | 
-LL | fn bar(foo: i32) {}
-   |        ^^^ cannot be named the same as a static
-
-error[E0530]: function parameters cannot shadow statics
-  --> $DIR/issue-23716.rs:13:13
-   |
-LL | use self::submod::answer;
-   |     -------------------- the static `answer` is imported here
-LL | 
-LL | fn question(answer: i32) {}
-   |             ^^^^^^ cannot be named the same as a static
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/issues/issue-23968-const-not-overflow.rs b/src/test/ui/issues/issue-23968-const-not-overflow.rs
deleted file mode 100644 (file)
index b959302..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-const U8_MAX_HALF: u8 = !0u8 / 2;
-const U16_MAX_HALF: u16 = !0u16 / 2;
-const U32_MAX_HALF: u32 = !0u32 / 2;
-const U64_MAX_HALF: u64 = !0u64 / 2;
-
-fn main() {
-    assert_eq!(U8_MAX_HALF, 0x7f);
-    assert_eq!(U16_MAX_HALF, 0x7fff);
-    assert_eq!(U32_MAX_HALF, 0x7fff_ffff);
-    assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff);
-}
diff --git a/src/test/ui/issues/issue-24010.rs b/src/test/ui/issues/issue-24010.rs
deleted file mode 100644 (file)
index f181853..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-
-trait Foo: Fn(i32) -> i32 + Send {}
-
-impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
-
-fn wants_foo(f: Box<dyn Foo>) -> i32 {
-    f(42)
-}
-
-fn main() {
-    let f = Box::new(|x| x);
-    assert_eq!(wants_foo(f), 42);
-}
diff --git a/src/test/ui/issues/issue-24313.rs b/src/test/ui/issues/issue-24313.rs
deleted file mode 100644 (file)
index c28b4ca..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// run-pass
-// ignore-emscripten no threads
-// ignore-sgx no processes
-
-use std::thread;
-use std::env;
-use std::process::Command;
-
-struct Handle(i32);
-
-impl Drop for Handle {
-    fn drop(&mut self) { panic!(); }
-}
-
-thread_local!(static HANDLE: Handle = Handle(0));
-
-fn main() {
-    let args = env::args().collect::<Vec<_>>();
-    if args.len() == 1 {
-        let out = Command::new(&args[0]).arg("test").output().unwrap();
-        let stderr = std::str::from_utf8(&out.stderr).unwrap();
-        assert!(stderr.contains("panicked at 'explicit panic'"),
-                "bad failure message:\n{}\n", stderr);
-    } else {
-        // TLS dtors are not always run on process exit
-        thread::spawn(|| {
-            HANDLE.with(|h| {
-                println!("{}", h.0);
-            });
-        }).join().unwrap();
-    }
-}
diff --git a/src/test/ui/issues/issue-2444.rs b/src/test/ui/issues/issue-2444.rs
deleted file mode 100644 (file)
index ac0d050..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-fail
-// error-pattern:explicit panic
-// ignore-emscripten no processes
-
-use std::sync::Arc;
-
-enum Err<T> {
-    Errr(Arc<T>),
-}
-
-fn foo() -> Err<isize> {
-    panic!();
-}
-
-fn main() {
-    let _f = foo();
-}
diff --git a/src/test/ui/issues/issue-26251.rs b/src/test/ui/issues/issue-26251.rs
deleted file mode 100644 (file)
index a3e26a4..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-#![allow(overlapping_range_endpoints)]
-
-fn main() {
-    let x = 'a';
-
-    let y = match x {
-        'a'..='b' if false => "one",
-        'a' => "two",
-        'a'..='b' => "three",
-        _ => panic!("what?"),
-    };
-
-    assert_eq!(y, "two");
-}
diff --git a/src/test/ui/issues/issue-26448-1.rs b/src/test/ui/issues/issue-26448-1.rs
deleted file mode 100644 (file)
index 7d2d75b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-
-pub trait Foo<T> {
-    fn foo(self) -> T;
-}
-
-impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
-    fn foo(self) -> T {
-        panic!();
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/issues/issue-26448-2.rs
deleted file mode 100644 (file)
index c60e06c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// check-pass
-
-pub struct Bar<T> {
-    items: Vec<&'static str>,
-    inner: T,
-}
-
-pub trait IntoBar<T> {
-    fn into_bar(self) -> Bar<T>;
-}
-
-impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
-    fn into_bar(self) -> Bar<T> {
-        Bar {
-            items: Vec::new(),
-            inner: self.into(),
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/issues/issue-26448-3.rs
deleted file mode 100644 (file)
index d48022c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// check-pass
-
-pub struct Item {
-    _inner: &'static str,
-}
-
-pub struct Bar<T> {
-    items: Vec<Item>,
-    inner: T,
-}
-
-pub trait IntoBar<T> {
-    fn into_bar(self) -> Bar<T>;
-}
-
-impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
-    fn into_bar(self) -> Bar<T> {
-        Bar {
-            items: Vec::new(),
-            inner: self.into(),
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26638.rs b/src/test/ui/issues/issue-26638.rs
deleted file mode 100644 (file)
index 72fe428..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn parse_type_3() -> &str { unimplemented!() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr
deleted file mode 100644 (file)
index bb7cdcb..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-26638.rs:1:62
-   |
-LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
-   |                     ------------------------------------     ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
-help: consider introducing a named lifetime parameter
-   |
-LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
-   |              ++++                                                 ++
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-26638.rs:4:40
-   |
-LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-   |                                        ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
-help: consider using the `'static` lifetime
-   |
-LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() }
-   |                                        ~~~~~~~~
-
-error[E0106]: missing lifetime specifier
-  --> $DIR/issue-26638.rs:7:22
-   |
-LL | fn parse_type_3() -> &str { unimplemented!() }
-   |                      ^ expected named lifetime parameter
-   |
-   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
-   |
-LL | fn parse_type_3() -> &'static str { unimplemented!() }
-   |                      ~~~~~~~~
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/issues/issue-26996.rs b/src/test/ui/issues/issue-26996.rs
deleted file mode 100644 (file)
index 84037b7..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-
-// This test is bogus (i.e., should be check-fail) during the period
-// where #54986 is implemented and #54987 is *not* implemented. For
-// now: just ignore it
-//
-// ignore-test
-
-// This test is checking that the write to `c.0` (which has been moved out of)
-// won't overwrite the state in `c2`.
-//
-// That's a fine thing to test when this code is accepted by the
-// compiler, and this code is being transcribed accordingly into
-// the ui test issue-21232-partial-init-and-use.rs
-
-fn main() {
-    let mut c = (1, "".to_owned());
-    match c {
-        c2 => {
-            c.0 = 2;
-            assert_eq!(c2.0, 1);
-        }
-    }
-}
diff --git a/src/test/ui/issues/issue-2748-b.rs b/src/test/ui/issues/issue-2748-b.rs
deleted file mode 100644 (file)
index 8df735a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-
-fn thing<'r>(x: &'r [isize]) -> &'r [isize] { x }
-
-pub fn main() {
-    let x = &[1,2,3];
-    let y = x;
-    let z = thing(x);
-    assert_eq!(z[2], x[2]);
-    assert_eq!(z[1], y[1]);
-}
diff --git a/src/test/ui/issues/issue-28324.mir.stderr b/src/test/ui/issues/issue-28324.mir.stderr
deleted file mode 100644 (file)
index aff8bf7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-28324.rs:8:24
-   |
-LL | pub static BAZ: u32 = *&error_message_count;
-   |                        ^^^^^^^^^^^^^^^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-28324.rs b/src/test/ui/issues/issue-28324.rs
deleted file mode 100644 (file)
index fbe83e3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-extern "C" {
-    static error_message_count: u32;
-}
-
-pub static BAZ: u32 = *&error_message_count;
-//~^ ERROR use of extern static is unsafe and requires
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-28324.thir.stderr b/src/test/ui/issues/issue-28324.thir.stderr
deleted file mode 100644 (file)
index c696c35..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-28324.rs:8:25
-   |
-LL | pub static BAZ: u32 = *&error_message_count;
-   |                         ^^^^^^^^^^^^^^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs b/src/test/ui/issues/issue-28498-ugeh-with-passed-to-fn.rs
deleted file mode 100644 (file)
index 23fd86a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// run-pass
-
-// Demonstrate the use of the unguarded escape hatch with a type param in negative position
-// to assert that destructor will not access any dead data.
-//
-// Compare with ui/span/issue28498-reject-lifetime-param.rs
-
-// Demonstrate that a type param in negative position causes dropck to reject code
-// that might indirectly access previously dropped value.
-//
-// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
-
-#![feature(dropck_eyepatch)]
-
-#[derive(Debug)]
-struct ScribbleOnDrop(String);
-
-impl Drop for ScribbleOnDrop {
-    fn drop(&mut self) {
-        self.0 = format!("DROPPED");
-    }
-}
-
-struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
-
-unsafe impl<#[may_dangle] T> Drop for Foo<T> {
-    fn drop(&mut self) {
-        // Use of `may_dangle` is sound, because destructor never passes a `self.1`
-        // to the callback (in `self.2`) despite having it available.
-        println!("Dropping Foo({}, _)", self.0);
-    }
-}
-
-fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
-
-fn main() {
-    let (last_dropped, foo0);
-    let (foo1, first_dropped);
-
-    last_dropped = ScribbleOnDrop(format!("last"));
-    first_dropped = ScribbleOnDrop(format!("first"));
-    foo0 = Foo(0, &last_dropped, Box::new(callback));
-    foo1 = Foo(1, &first_dropped, Box::new(callback));
-
-    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
-}
diff --git a/src/test/ui/issues/issue-28871.rs b/src/test/ui/issues/issue-28871.rs
deleted file mode 100644 (file)
index 210c783..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// check-pass
-// Regression test for #28871. The problem is that rustc encountered
-// two ways to project, one from a where clause and one from the where
-// clauses on the trait definition. (In fact, in this case, the where
-// clauses originated from the trait definition as well.) The true
-// cause of the error is that the trait definition where clauses are
-// not being normalized, and hence the two sources are considered in
-// conflict, and not a duplicate. Hacky solution is to prefer where
-// clauses over the data found in the trait definition.
-
-trait T {
-    type T;
-}
-
-struct S;
-impl T for S {
-    type T = S;
-}
-
-trait T2 {
-    type T: Iterator<Item=<S as T>::T>;
-}
-
-fn main() { }
diff --git a/src/test/ui/issues/issue-29084.rs b/src/test/ui/issues/issue-29084.rs
deleted file mode 100644 (file)
index d162526..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-macro_rules! foo {
-    ($d:expr) => {{
-        fn bar(d: u8) { }
-        bar(&mut $d);
-        //~^ ERROR mismatched types
-        //~| expected `u8`, found `&mut u8`
-    }}
-}
-
-fn main() {
-    foo!(0u8);
-    //~^ in this expansion of foo!
-}
diff --git a/src/test/ui/issues/issue-29084.stderr b/src/test/ui/issues/issue-29084.stderr
deleted file mode 100644 (file)
index a973e23..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-29084.rs:4:13
-   |
-LL |         bar(&mut $d);
-   |             ^^^^^^^ expected `u8`, found `&mut u8`
-...
-LL |     foo!(0u8);
-   |     --------- in this macro invocation
-   |
-   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-3021-c.rs b/src/test/ui/issues/issue-3021-c.rs
deleted file mode 100644 (file)
index 94ed1fd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-fn siphash<T>() {
-
-    trait U {
-        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
-        //~^ ERROR can't use generic parameters from outer function
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-3021-c.stderr b/src/test/ui/issues/issue-3021-c.stderr
deleted file mode 100644 (file)
index 8764ac8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-3021-c.rs:4:24
-   |
-LL | fn siphash<T>() {
-   |            - type parameter from outer function
-...
-LL |         fn g(&self, x: T) -> T;
-   |            -           ^ use of generic parameter from outer function
-   |            |
-   |            help: try using a local generic parameter instead: `g<T>`
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-3021-c.rs:4:30
-   |
-LL | fn siphash<T>() {
-   |            - type parameter from outer function
-...
-LL |         fn g(&self, x: T) -> T;
-   |            -                 ^ use of generic parameter from outer function
-   |            |
-   |            help: try using a local generic parameter instead: `g<T>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/issues/issue-3021.rs b/src/test/ui/issues/issue-3021.rs
deleted file mode 100644 (file)
index a672261..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-trait SipHash {
-    fn reset(&self);
-}
-
-fn siphash(k0 : u64) {
-    struct SipState {
-        v0: u64,
-    }
-
-    impl SipHash for SipState {
-        fn reset(&self) {
-           self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
-        }
-    }
-    panic!();
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-3021.stderr b/src/test/ui/issues/issue-3021.stderr
deleted file mode 100644 (file)
index d5b015e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0434]: can't capture dynamic environment in a fn item
-  --> $DIR/issue-3021.rs:12:22
-   |
-LL |            self.v0 = k0 ^ 0x736f6d6570736575;
-   |                      ^^
-   |
-   = help: use the `|| { ... }` closure form instead
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/issues/issue-30225.rs b/src/test/ui/issues/issue-30225.rs
deleted file mode 100644 (file)
index 4231533..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Regression test for #30225, which was an ICE that would trigger as
-// a result of a poor interaction between trait result caching and
-// type inference. Specifically, at that time, unification could cause
-// unrelated type variables to become instantiated, if subtyping
-// relationships existed. These relationships are now propagated
-// through obligations and hence everything works out fine.
-
-trait Foo<U,V> : Sized {
-    fn foo(self, u: Option<U>, v: Option<V>) {}
-}
-
-struct A;
-struct B;
-
-impl Foo<A, B> for () {}      // impl A
-impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
-
-fn toxic() {
-    // cache the resolution <() as Foo<$0,$1>> = impl A
-    let u = None;
-    let v = None;
-    Foo::foo((), u, v);
-}
-
-fn bomb() {
-    let mut u = None; // type is Option<$0>
-    let mut v = None; // type is Option<$1>
-    let mut x = None; // type is Option<$2>
-
-    Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
-    u = v; // mark $0 and $1 in a subtype relationship
-    //~^ ERROR mismatched types
-    x = Some(()); // set $2 = (), allowing impl selection
-                  // to proceed for <() as Foo<$0, $1>> = impl A.
-                  // kaboom, this *used* to trigge an ICE
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-30225.stderr b/src/test/ui/issues/issue-30225.stderr
deleted file mode 100644 (file)
index ccd05fa..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-30225.rs:31:9
-   |
-LL |     u = v; // mark $0 and $1 in a subtype relationship
-   |         ^ expected struct `A`, found struct `B`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-30355.rs b/src/test/ui/issues/issue-30355.rs
deleted file mode 100644 (file)
index 6ff5b37..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct X([u8]);
-
-pub static Y: &'static X = {
-    const Y: &'static [u8] = b"";
-    &X(*Y)
-    //~^ ERROR E0277
-};
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr
deleted file mode 100644 (file)
index 71bbdf5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-30355.rs:5:8
-   |
-LL |     &X(*Y)
-   |        ^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[u8]`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-31076.rs b/src/test/ui/issues/issue-31076.rs
deleted file mode 100644 (file)
index cdb196d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(no_core, lang_items)]
-#![no_core]
-
-#[lang="sized"]
-trait Sized {}
-
-#[lang="add"]
-trait Add<T> {}
-
-impl Add<i32> for i32 {}
-
-fn main() {
-    let x = 5 + 6;
-    //~^ ERROR cannot add `i32` to `{integer}`
-    let y = 5i32 + 6i32;
-    //~^ ERROR cannot add `i32` to `i32`
-}
diff --git a/src/test/ui/issues/issue-31076.stderr b/src/test/ui/issues/issue-31076.stderr
deleted file mode 100644 (file)
index ac0d9dc..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0369]: cannot add `i32` to `{integer}`
-  --> $DIR/issue-31076.rs:13:15
-   |
-LL |     let x = 5 + 6;
-   |             - ^ - i32
-   |             |
-   |             {integer}
-
-error[E0369]: cannot add `i32` to `i32`
-  --> $DIR/issue-31076.rs:15:18
-   |
-LL |     let y = 5i32 + 6i32;
-   |             ---- ^ ---- i32
-   |             |
-   |             i32
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/issues/issue-31804.rs b/src/test/ui/issues/issue-31804.rs
deleted file mode 100644 (file)
index d056b77..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// Test that error recovery in the parser to an EOF does not give an infinite
-// spew of errors.
-
-fn main() {
-    let
-} //~ ERROR expected pattern, found `}`
diff --git a/src/test/ui/issues/issue-31804.stderr b/src/test/ui/issues/issue-31804.stderr
deleted file mode 100644 (file)
index 76e68b0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected pattern, found `}`
-  --> $DIR/issue-31804.rs:6:1
-   |
-LL | }
-   | ^ expected pattern
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-31845.rs b/src/test/ui/issues/issue-31845.rs
deleted file mode 100644 (file)
index f6dc115..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Checks lexical scopes cannot see through normal module boundaries
-
-fn f() {
-    fn g() {}
-    mod foo {
-        fn h() {
-           g(); //~ ERROR cannot find function `g` in this scope
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-31845.stderr b/src/test/ui/issues/issue-31845.stderr
deleted file mode 100644 (file)
index 5628193..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find function `g` in this scope
-  --> $DIR/issue-31845.rs:7:12
-   |
-LL |            g();
-   |            ^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-3211.rs b/src/test/ui/issues/issue-3211.rs
deleted file mode 100644 (file)
index 49dd4fa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-pub fn main() {
-    let mut x = 0;
-    for _ in 0..4096 { x += 1; }
-    assert_eq!(x, 4096);
-    println!("x = {}", x);
-}
diff --git a/src/test/ui/issues/issue-32201.rs b/src/test/ui/issues/issue-32201.rs
deleted file mode 100644 (file)
index f27bb1c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-extern "C" {
-    fn foo(a: i32, ...);
-}
-
-fn bar(_: *const u8) {}
-
-fn main() {
-    unsafe {
-        foo(0, bar);
-        //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
-        //~| HELP cast the value to `fn(*const u8)`
-    }
-}
diff --git a/src/test/ui/issues/issue-32201.stderr b/src/test/ui/issues/issue-32201.stderr
deleted file mode 100644 (file)
index cedb587..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
-  --> $DIR/issue-32201.rs:9:16
-   |
-LL |         foo(0, bar);
-   |                ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0617`.
diff --git a/src/test/ui/issues/issue-333.rs b/src/test/ui/issues/issue-333.rs
deleted file mode 100644 (file)
index 0753aaa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-
-fn quux<T>(x: T) -> T { let f = id::<T>; return f(x); }
-
-fn id<T>(x: T) -> T { return x; }
-
-pub fn main() { assert_eq!(quux(10), 10); }
diff --git a/src/test/ui/issues/issue-34028.rs b/src/test/ui/issues/issue-34028.rs
deleted file mode 100644 (file)
index d761c0c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-
-macro_rules! m {
-    () => { #[cfg(any())] fn f() {} }
-}
-
-trait T {}
-impl T for () { m!(); }
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-34171.rs b/src/test/ui/issues/issue-34171.rs
deleted file mode 100644 (file)
index 157c58c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-
-macro_rules! null { ($i:tt) => {} }
-macro_rules! apply_null {
-    ($i:item) => { null! { $i } }
-}
-
-fn main() {
-    apply_null!(#[cfg(all())] fn f() {});
-}
diff --git a/src/test/ui/issues/issue-34255-1.rs b/src/test/ui/issues/issue-34255-1.rs
deleted file mode 100644 (file)
index c70cd8b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-enum Test {
-    Drill {
-        field: i32,
-    }
-}
-
-fn main() {
-    Test::Drill(field: 42);
-    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
-}
diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr
deleted file mode 100644 (file)
index fbff75e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: invalid `struct` delimiters or `fn` call arguments
-  --> $DIR/issue-34255-1.rs:8:5
-   |
-LL |     Test::Drill(field: 42);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: if `Test::Drill` is a struct, use braces as delimiters
-   |
-LL |     Test::Drill { field: 42 };
-   |                 ~           ~
-help: if `Test::Drill` is a function, use the arguments directly
-   |
-LL -     Test::Drill(field: 42);
-LL +     Test::Drill(42);
-   | 
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-35546.rs b/src/test/ui/issues/issue-35546.rs
deleted file mode 100644 (file)
index 004679a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// build-pass
-#![allow(dead_code)]
-// Regression test for #35546. Check that we are able to codegen
-// this. Before we had problems because of the drop glue signature
-// around dropping a trait object (specifically, when dropping the
-// `value` field of `Node<Send>`).
-
-struct Node<T: ?Sized + Send> {
-    next: Option<Box<Node<dyn Send>>>,
-    value: T,
-}
-
-fn clear(head: &mut Option<Box<Node<dyn Send>>>) {
-    match head.take() {
-        Some(node) => *head = node.next,
-        None => (),
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-37175.rs b/src/test/ui/issues/issue-37175.rs
deleted file mode 100644 (file)
index 9ec9d48..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// run-pass
-macro_rules! m { (<$t:ty>) => { stringify!($t) } }
-fn main() {
-    println!("{}", m!(<Vec<i32>>));
-}
diff --git a/src/test/ui/issues/issue-37366.rs b/src/test/ui/issues/issue-37366.rs
deleted file mode 100644 (file)
index acc2f3e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// check-pass
-// ignore-emscripten
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-macro_rules! interrupt_handler {
-    () => {
-        unsafe fn _interrupt_handler() {
-            llvm_asm!("pop  eax" :::: "intel");
-        }
-    }
-}
-interrupt_handler!{}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs
deleted file mode 100644 (file)
index 35b63bd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-const fn x() {
-    let t = true;
-    let x = || t; //~ ERROR function pointer
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr
deleted file mode 100644 (file)
index 54b60df..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: function pointers cannot appear in constant functions
-  --> $DIR/issue-37550.rs:3:9
-   |
-LL |     let x = || t;
-   |         ^
-   |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-37991.rs b/src/test/ui/issues/issue-37991.rs
deleted file mode 100644 (file)
index a6ac4d5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-
-const fn foo() -> i64 {
-    3
-}
-
-const fn bar(x: i64) -> i64 {
-    x*2
-}
-
-fn main() {
-    let val = &(foo() % 2);
-    assert_eq!(*val, 1);
-
-    let val2 = &(bar(1+1) % 3);
-    assert_eq!(*val2, 1);
-}
diff --git a/src/test/ui/issues/issue-38604.rs b/src/test/ui/issues/issue-38604.rs
deleted file mode 100644 (file)
index 002a3c4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-trait Q<T:?Sized> {}
-trait Foo where u32: Q<Self> {
-    fn foo(&self);
-}
-
-impl Q<()> for u32 {}
-impl Foo for () {
-    fn foo(&self) {
-        println!("foo!");
-    }
-}
-
-fn main() {
-    let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
-        Box::new(()); //~ ERROR `Foo` cannot be made into an object
-}
diff --git a/src/test/ui/issues/issue-38604.stderr b/src/test/ui/issues/issue-38604.stderr
deleted file mode 100644 (file)
index d41488c..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/issue-38604.rs:14:13
-   |
-LL |     let _f: Box<dyn Foo> =
-   |             ^^^^^^^^^^^^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-38604.rs:2:22
-   |
-LL | trait Foo where u32: Q<Self> {
-   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
-   |       |
-   |       this trait cannot be made into an object...
-
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/issue-38604.rs:15:9
-   |
-LL |         Box::new(());
-   |         ^^^^^^^^^^^^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-38604.rs:2:22
-   |
-LL | trait Foo where u32: Q<Self> {
-   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
-   |       |
-   |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<()>`
-   = note: required by cast to type `Box<dyn Foo>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-39388.rs b/src/test/ui/issues/issue-39388.rs
deleted file mode 100644 (file)
index a8e31a6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![allow(unused_macros)]
-
-macro_rules! assign {
-    (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
-        $($a)* = $($b)*
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-39388.stderr b/src/test/ui/issues/issue-39388.stderr
deleted file mode 100644 (file)
index 62e7dff..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of: `*`, `+`, or `?`
-  --> $DIR/issue-39388.rs:4:22
-   |
-LL |     (($($a:tt)*) = ($($b:tt))*) => {
-   |                      ^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-3973.rs b/src/test/ui/issues/issue-3973.rs
deleted file mode 100644 (file)
index a5ed5b8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-struct Point {
-    x: f64,
-    y: f64,
-}
-
-trait ToString_ {
-    fn to_string(&self) -> String;
-}
-
-impl ToString_ for Point {
-    fn new(x: f64, y: f64) -> Point {
-    //~^ ERROR method `new` is not a member of trait `ToString_`
-        Point { x: x, y: y }
-    }
-
-    fn to_string(&self) -> String {
-        format!("({}, {})", self.x, self.y)
-    }
-}
-
-fn main() {
-    let p = Point::new(0.0, 0.0);
-    //~^ ERROR no function or associated item named `new` found for struct `Point`
-    println!("{}", p.to_string());
-}
diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr
deleted file mode 100644 (file)
index 63282e8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0407]: method `new` is not a member of trait `ToString_`
-  --> $DIR/issue-3973.rs:11:5
-   |
-LL | /     fn new(x: f64, y: f64) -> Point {
-LL | |
-LL | |         Point { x: x, y: y }
-LL | |     }
-   | |_____^ not a member of trait `ToString_`
-
-error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
-  --> $DIR/issue-3973.rs:22:20
-   |
-LL | struct Point {
-   | ------------ function or associated item `new` not found for this
-...
-LL |     let p = Point::new(0.0, 0.0);
-   |                    ^^^ function or associated item not found in `Point`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0407, E0599.
-For more information about an error, try `rustc --explain E0407`.
diff --git a/src/test/ui/issues/issue-39823.rs b/src/test/ui/issues/issue-39823.rs
deleted file mode 100644 (file)
index 148cf52..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// run-pass
-// aux-build:issue-39823.rs
-
-extern crate issue_39823;
-use issue_39823::{RemoteC, RemoteG};
-
-#[derive(Debug, PartialEq)]
-struct LocalC(u32);
-
-#[derive(Debug, PartialEq)]
-struct LocalG<T>(T);
-
-fn main() {
-    let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC;
-    assert_eq!(virtual_localc(1), LocalC(1));
-
-    let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG;
-    assert_eq!(virtual_localg(1), LocalG(1));
-
-    let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC;
-    assert_eq!(virtual_remotec(1), RemoteC(1));
-
-    let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG;
-    assert_eq!(virtual_remoteg(1), RemoteG(1));
-}
diff --git a/src/test/ui/issues/issue-40770.rs b/src/test/ui/issues/issue-40770.rs
deleted file mode 100644 (file)
index c9713c1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-#![allow(unused_macros)]
-macro_rules! m {
-    ($e:expr) => {
-        macro_rules! n { () => { $e } }
-    }
-}
-
-fn main() {
-    m!(foo!());
-}
diff --git a/src/test/ui/issues/issue-40962.rs b/src/test/ui/issues/issue-40962.rs
deleted file mode 100644 (file)
index 7b91c06..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// check-pass
-macro_rules! m {
-    ($i:meta) => {
-        #[derive($i)]
-        struct S;
-    }
-}
-
-m!(Clone);
-
-fn main() {}
index 7875b432d7be4cf53e326c20cf0369e3de28bb61..10c363479a374a6288175bef782f17f0dca4b3c0 100644 (file)
@@ -4,9 +4,9 @@
 trait A {
 }
 
-impl<T> Drop for T where T: A { //~ ERROR E0119
-                                //~^ ERROR E0120
-                                //~| ERROR E0210
+impl<T> Drop for T where T: A {
+    //~^ ERROR E0120
+    //~| ERROR E0210
     fn drop(&mut self) {
     }
 }
index 11d77857d60cc96eb941ead57238bb92ece47586..fcbb4014025f152eb97c312c00abe90b63e910af 100644 (file)
@@ -1,13 +1,11 @@
-error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `std::boxed::Box<_, _>`
-  --> $DIR/issue-41974.rs:7:1
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/issue-41974.rs:7:6
    |
 LL | impl<T> Drop for T where T: A {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^ type parameter `T` must be used as the type parameter for some local type
    |
-   = note: conflicting implementation in crate `alloc`:
-           - impl<T, A> Drop for Box<T, A>
-             where A: Allocator, T: ?Sized;
-   = note: downstream crates may implement trait `A` for type `std::boxed::Box<_, _>`
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
+   = note: only traits defined in the current crate can be implemented for a type parameter
 
 error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
   --> $DIR/issue-41974.rs:7:18
@@ -15,16 +13,7 @@ error[E0120]: the `Drop` trait may only be implemented for structs, enums, and u
 LL | impl<T> Drop for T where T: A {
    |                  ^ must be a struct, enum, or union
 
-error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
-  --> $DIR/issue-41974.rs:7:6
-   |
-LL | impl<T> Drop for T where T: A {
-   |      ^ type parameter `T` must be used as the type parameter for some local type
-   |
-   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
-   = note: only traits defined in the current crate can be implemented for a type parameter
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0119, E0120, E0210.
-For more information about an error, try `rustc --explain E0119`.
+Some errors have detailed explanations: E0120, E0210.
+For more information about an error, try `rustc --explain E0120`.
diff --git a/src/test/ui/issues/issue-42463.rs b/src/test/ui/issues/issue-42463.rs
deleted file mode 100644 (file)
index 51d6ea3..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// run-pass
-use std::ops::{Deref, DerefMut};
-
-struct CheckedDeref<T, F> {
-    value: T,
-    check: F
-}
-
-impl<F: Fn(&T) -> bool, T> Deref for CheckedDeref<T, F> {
-    type Target = T;
-    fn deref(&self) -> &T {
-        assert!((self.check)(&self.value));
-        &self.value
-    }
-}
-
-impl<F: Fn(&T) -> bool, T> DerefMut for CheckedDeref<T, F> {
-    fn deref_mut(&mut self) -> &mut T {
-        assert!((self.check)(&self.value));
-        &mut self.value
-    }
-}
-
-
-fn main() {
-    let mut v = CheckedDeref {
-        value: vec![0],
-        check: |v: &Vec<_>| !v.is_empty()
-    };
-    v.push(1);
-    assert_eq!(*v, vec![0, 1]);
-}
diff --git a/src/test/ui/issues/issue-42679.rs b/src/test/ui/issues/issue-42679.rs
deleted file mode 100644 (file)
index 596309f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-#![feature(box_syntax)]
-#![feature(box_patterns)]
-
-#[derive(Debug, PartialEq)]
-enum Test {
-    Foo(usize),
-    Bar(isize),
-}
-
-fn main() {
-    let a = box Test::Foo(10);
-    let b = box Test::Bar(-20);
-    match (a, b) {
-        (_, box Test::Foo(_)) => unreachable!(),
-        (box Test::Foo(x), b) => {
-            assert_eq!(x, 10);
-            assert_eq!(b, box Test::Bar(-20));
-        },
-        _ => unreachable!(),
-    }
-}
diff --git a/src/test/ui/issues/issue-42747.rs b/src/test/ui/issues/issue-42747.rs
deleted file mode 100644 (file)
index fec6587..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// run-pass
-macro_rules! fooN {
-    ($cur:ident $prev:ty) => {
-        #[allow(dead_code)]
-        enum $cur {
-            Empty,
-            First($prev),
-            Second($prev),
-            Third($prev),
-            Fourth($prev),
-        }
-    }
-}
-
-fooN!(Foo0 ());
-fooN!(Foo1 Foo0);
-fooN!(Foo2 Foo1);
-fooN!(Foo3 Foo2);
-fooN!(Foo4 Foo3);
-fooN!(Foo5 Foo4);
-fooN!(Foo6 Foo5);
-fooN!(Foo7 Foo6);
-fooN!(Foo8 Foo7);
-fooN!(Foo9 Foo8);
-fooN!(Foo10 Foo9);
-fooN!(Foo11 Foo10);
-fooN!(Foo12 Foo11);
-fooN!(Foo13 Foo12);
-fooN!(Foo14 Foo13);
-fooN!(Foo15 Foo14);
-fooN!(Foo16 Foo15);
-fooN!(Foo17 Foo16);
-fooN!(Foo18 Foo17);
-fooN!(Foo19 Foo18);
-fooN!(Foo20 Foo19);
-fooN!(Foo21 Foo20);
-fooN!(Foo22 Foo21);
-fooN!(Foo23 Foo22);
-fooN!(Foo24 Foo23);
-fooN!(Foo25 Foo24);
-fooN!(Foo26 Foo25);
-fooN!(Foo27 Foo26);
-
-fn main() {
-    let _foo = Foo27::Empty;
-}
diff --git a/src/test/ui/issues/issue-43189.rs b/src/test/ui/issues/issue-43189.rs
deleted file mode 100644 (file)
index ce667a5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Issue 46112: An extern crate pub re-exporting libcore was causing
-// paths rooted from `std` to be misrendered in the diagnostic output.
-
-// ignore-windows
-// aux-build:xcrate-issue-43189-a.rs
-// aux-build:xcrate-issue-43189-b.rs
-
-extern crate xcrate_issue_43189_b;
-fn main() {
-    ().a();
-    //~^ ERROR no method named `a` found
-}
diff --git a/src/test/ui/issues/issue-43189.stderr b/src/test/ui/issues/issue-43189.stderr
deleted file mode 100644 (file)
index caf7530..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0599]: no method named `a` found for unit type `()` in the current scope
-  --> $DIR/issue-43189.rs:10:8
-   |
-LL |     ().a();
-   |        ^ method not found in `()`
-   |
-  ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
-   |
-LL |     fn a(&self) {}
-   |        - the method is available for `()` here
-   |
-   = help: items from traits can only be used if the trait is in scope
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
-   |
-LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-4401.rs b/src/test/ui/issues/issue-4401.rs
deleted file mode 100644 (file)
index fef73fb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-pub fn main() {
-    let mut count = 0;
-    for _ in 0..999_999 { count += 1; }
-    assert_eq!(count, 999_999);
-    println!("{}", count);
-}
diff --git a/src/test/ui/issues/issue-4448.rs b/src/test/ui/issues/issue-4448.rs
deleted file mode 100644 (file)
index 27d0326..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-
-use std::sync::mpsc::channel;
-use std::thread;
-
-pub fn main() {
-    let (tx, rx) = channel::<&'static str>();
-
-    let t = thread::spawn(move|| {
-        assert_eq!(rx.recv().unwrap(), "hello, world");
-    });
-
-    tx.send("hello, world").unwrap();
-    t.join().ok().unwrap();
-}
diff --git a/src/test/ui/issues/issue-45124.rs b/src/test/ui/issues/issue-45124.rs
deleted file mode 100644 (file)
index 942014c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-#![allow(unreachable_code)]
-// compile-flags: --edition 2018
-
-#![feature(try_blocks)]
-
-fn main() {
-    let mut a = 0;
-    let () = {
-        let _: Result<(), ()> = try {
-            let _ = Err(())?;
-            return
-        };
-        a += 1;
-    };
-    a += 2;
-    assert_eq!(a, 3);
-}
diff --git a/src/test/ui/issues/issue-45152.rs b/src/test/ui/issues/issue-45152.rs
deleted file mode 100644 (file)
index fb1c9fb..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#![allow(unused_variables)]
-#![feature(unsize, coerce_unsized)]
-
-#[repr(packed)]
-struct UnalignedPtr<'a, T: ?Sized>
-    where T: 'a,
-{
-    data: &'a T,
-}
-
-fn main() {
-
-    impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
-        where
-        T: std::marker::Unsize<U> + ?Sized,
-        U: ?Sized,
-    { }
-
-    let arr = [1, 2, 3];
-    let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
-    let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
-}
diff --git a/src/test/ui/issues/issue-46095.rs b/src/test/ui/issues/issue-46095.rs
deleted file mode 100644 (file)
index 59ddb60..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-struct A;
-
-impl A {
-    fn take_mutably(&mut self) {}
-}
-
-fn identity<T>(t: T) -> T {
-    t
-}
-
-// Issue 46095
-// Built-in indexing should be used even when the index is not
-// trivially an integer
-// Overloaded indexing would cause wrapped to be borrowed mutably
-
-fn main() {
-    let mut a1 = A;
-    let mut a2 = A;
-
-    let wrapped = [&mut a1, &mut a2];
-
-    {
-        wrapped[0 + 1 - 1].take_mutably();
-    }
-
-    {
-        wrapped[identity(0)].take_mutably();
-    }
-}
diff --git a/src/test/ui/issues/issue-46112.rs b/src/test/ui/issues/issue-46112.rs
deleted file mode 100644 (file)
index 0cdd2c2..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Issue 46112: An extern crate pub re-exporting libcore was causing
-// paths rooted from `std` to be misrendered in the diagnostic output.
-
-// ignore-windows
-// aux-build:xcrate-issue-46112-rexport-core.rs
-
-extern crate xcrate_issue_46112_rexport_core;
-fn test(r: Result<Option<()>, &'static str>) { }
-fn main() { test(Ok(())); }
-//~^ mismatched types
diff --git a/src/test/ui/issues/issue-46112.stderr b/src/test/ui/issues/issue-46112.stderr
deleted file mode 100644 (file)
index ec05fbe..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-46112.rs:9:21
-   |
-LL | fn main() { test(Ok(())); }
-   |                     ^^
-   |                     |
-   |                     expected enum `Option`, found `()`
-   |                     help: try using a variant of the expected enum: `Some(())`
-   |
-   = note:   expected enum `Option<()>`
-           found unit type `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-47139-1.rs b/src/test/ui/issues/issue-47139-1.rs
deleted file mode 100644 (file)
index c55fc34..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// run-pass
-// Regression test for issue #47139:
-//
-// Coherence was encountering an (unnecessary) overflow trying to
-// decide if the two impls of dummy overlap.
-//
-// The overflow went something like:
-//
-// - `&'a ?T: Insertable` ?
-// - let ?T = Option<?U> ?
-// - `Option<?U>: Insertable` ?
-// - `Option<&'a ?U>: Insertable` ?
-// - `&'a ?U: Insertable` ?
-//
-// While somewhere in the middle, a projection would occur, which
-// broke cycle detection.
-//
-// It turned out that this cycle was being kicked off due to some
-// extended diagnostic attempts in coherence, so removing those
-// sidestepped the issue for now.
-
-#![allow(dead_code)]
-
-pub trait Insertable {
-    type Values;
-
-    fn values(self) -> Self::Values;
-}
-
-impl<T> Insertable for Option<T>
-    where
-    T: Insertable,
-    T::Values: Default,
-{
-    type Values = T::Values;
-
-    fn values(self) -> Self::Values {
-        self.map(Insertable::values).unwrap_or_default()
-    }
-}
-
-impl<'a, T> Insertable for &'a Option<T>
-    where
-    Option<&'a T>: Insertable,
-{
-    type Values = <Option<&'a T> as Insertable>::Values;
-
-    fn values(self) -> Self::Values {
-        self.as_ref().values()
-    }
-}
-
-impl<'a, T> Insertable for &'a [T]
-{
-    type Values = Self;
-
-    fn values(self) -> Self::Values {
-        self
-    }
-}
-
-trait Unimplemented { }
-
-trait Dummy { }
-
-struct Foo<T> { t: T }
-
-impl<'a, U> Dummy for Foo<&'a U>
-    where &'a U: Insertable
-{
-}
-
-impl<T> Dummy for T
-    where T: Unimplemented
-{ }
-
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/issues/issue-49040.rs
deleted file mode 100644 (file)
index b7a541d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![allow(unused_variables)]; //~ ERROR expected item, found `;`
-//~^ ERROR `main` function
-fn foo() {}
diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr
deleted file mode 100644 (file)
index 56befe3..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: expected item, found `;`
-  --> $DIR/issue-49040.rs:1:28
-   |
-LL | #![allow(unused_variables)];
-   |                            ^ help: remove this semicolon
-
-error[E0601]: `main` function not found in crate `issue_49040`
-  --> $DIR/issue-49040.rs:1:1
-   |
-LL | #![allow(unused_variables)];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/issues/issue-49579.rs b/src/test/ui/issues/issue-49579.rs
deleted file mode 100644 (file)
index 98de014..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-
-fn fibs(n: u32) -> impl Iterator<Item=u128> {
-    (0 .. n)
-    .scan((0, 1), |st, _| {
-        *st = (st.1, st.0 + st.1);
-        Some(*st)
-    })
-    .map(&|(f, _)| f)
-}
-
-fn main() {
-    println!("{:?}", fibs(10).collect::<Vec<_>>());
-}
diff --git a/src/test/ui/issues/issue-49685.rs b/src/test/ui/issues/issue-49685.rs
deleted file mode 100644 (file)
index fb328d6..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-// Regression test for #49685: drop elaboration was not revealing the
-// value of `impl Trait` returns, leading to an ICE.
-
-fn main() {
-    let _ = Some(())
-        .into_iter()
-        .flat_map(|_| Some(()).into_iter().flat_map(func));
-}
-
-fn func(_: ()) -> impl Iterator<Item = ()> {
-    Some(()).into_iter().flat_map(|_| vec![])
-}
diff --git a/src/test/ui/issues/issue-50731.rs b/src/test/ui/issues/issue-50731.rs
deleted file mode 100644 (file)
index 209c1e1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// run-pass
-enum Void {}
-fn foo(_: Result<(Void, u32), (Void, String)>) {}
-fn main() {
-    let _: fn(_) = foo;
-}
diff --git a/src/test/ui/issues/issue-5099.rs b/src/test/ui/issues/issue-5099.rs
deleted file mode 100644 (file)
index b5abccb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-trait B <A> {
-    fn a() -> A {
-        this.a //~ ERROR cannot find value `this` in this scope
-    }
-    fn b(x: i32) {
-        this.b(x); //~ ERROR cannot find value `this` in this scope
-    }
-    fn c() {
-        let _ = || this.a; //~ ERROR cannot find value `this` in this scope
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-5099.stderr b/src/test/ui/issues/issue-5099.stderr
deleted file mode 100644 (file)
index e9b2a9c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-error[E0425]: cannot find value `this` in this scope
-  --> $DIR/issue-5099.rs:3:9
-   |
-LL |         this.a
-   |         ^^^^ not found in this scope
-   |
-help: you might have meant to use `self` here instead
-   |
-LL |         self.a
-   |         ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
-   |
-LL |     fn a(&self) -> A {
-   |          +++++
-
-error[E0425]: cannot find value `this` in this scope
-  --> $DIR/issue-5099.rs:6:9
-   |
-LL |         this.b(x);
-   |         ^^^^ not found in this scope
-   |
-help: you might have meant to use `self` here instead
-   |
-LL |         self.b(x);
-   |         ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
-   |
-LL |     fn b(&self, x: i32) {
-   |          ++++++
-
-error[E0425]: cannot find value `this` in this scope
-  --> $DIR/issue-5099.rs:9:20
-   |
-LL |         let _ = || this.a;
-   |                    ^^^^ not found in this scope
-   |
-help: you might have meant to use `self` here instead
-   |
-LL |         let _ = || self.a;
-   |                    ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
-   |
-LL |     fn c(&self) {
-   |          +++++
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-50993.rs b/src/test/ui/issues/issue-50993.rs
deleted file mode 100644 (file)
index e6a9451..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags: --crate-type dylib --target thumbv7em-none-eabihf
-// needs-llvm-components: arm
-// build-pass
-// error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
-
-#![feature(no_core)]
-
-#![no_std]
-#![no_core]
diff --git a/src/test/ui/issues/issue-50993.stderr b/src/test/ui/issues/issue-50993.stderr
deleted file mode 100644 (file)
index 45cbfef..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-warning: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/issues/issue-51185.rs b/src/test/ui/issues/issue-51185.rs
deleted file mode 100644 (file)
index 52a2b25..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-fn foo() -> impl Into<for<'a> fn(&'a ())> {
-    (|_| {}) as for<'a> fn(&'a ())
-}
-
-fn main() {
-    foo().into()(&());
-}
diff --git a/src/test/ui/issues/issue-51345.rs b/src/test/ui/issues/issue-51345.rs
deleted file mode 100644 (file)
index 15571e8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-#![allow(unreachable_code)]
-
-fn main() {
-    let mut v = Vec::new();
-
-    loop { v.push(break) }
-}
diff --git a/src/test/ui/issues/issue-51582.rs b/src/test/ui/issues/issue-51582.rs
deleted file mode 100644 (file)
index 40a70c6..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-#![feature(core_intrinsics)]
-
-#[repr(i8)]
-pub enum Enum {
-    VariantA,
-    VariantB,
-}
-
-fn make_b() -> Enum { Enum::VariantB }
-
-fn main() {
-    assert_eq!(1, make_b() as i8);
-    assert_eq!(1, make_b() as u8);
-    assert_eq!(1, make_b() as i32);
-    assert_eq!(1, make_b() as u32);
-    assert_eq!(1, std::intrinsics::discriminant_value(&make_b()));
-}
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.rs b/src/test/ui/issues/issue-53787-inline-assembler-macro.rs
deleted file mode 100644 (file)
index d9fe7ca..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
-
-// build-fail
-// ignore-emscripten
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-macro_rules! fake_jump {
-    ($id:expr) => {
-        unsafe {
-            llvm_asm!(
-            "
-            jmp $0
-            lea eax, [ebx]
-            xor eax, 0xDEADBEEF
-            retn
-            $0:
-            "::"0"($id)::"volatile", "intel");
-        }
-    };
-}
-
-fn main() {
-    fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
-    println!("Hello, world!");
-}
diff --git a/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr b/src/test/ui/issues/issue-53787-inline-assembler-macro.stderr
deleted file mode 100644 (file)
index fd755e3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/issue-53787-inline-assembler-macro.rs:25:16
-   |
-LL |     fake_jump!("FirstFunc");
-   |                ^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/issues/issue-54467.rs b/src/test/ui/issues/issue-54467.rs
deleted file mode 100644 (file)
index 734bf27..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// run-pass
-
-pub trait Stream {
-    type Item;
-    type Error;
-}
-
-pub trait ParseError<I> {
-    type Output;
-}
-
-impl ParseError<char> for u32 {
-    type Output = ();
-}
-
-impl Stream for () {
-    type Item = char;
-    type Error = u32;
-}
-
-pub struct Lex<'a, I>
-    where I: Stream,
-          I::Error: ParseError<char>,
-          <<I as Stream>::Error as ParseError<char>>::Output: 'a
-{
-    x: &'a <I::Error as ParseError<char>>::Output
-}
-
-pub struct Reserved<'a, I> where
-    I: Stream<Item=char> + 'a,
-    I::Error: ParseError<I::Item>,
-    <<I as Stream>::Error as ParseError<char>>::Output: 'a
-
-{
-    x: Lex<'a, I>
-}
-
-fn main() {
-    let r: Reserved<()> = Reserved {
-        x: Lex {
-            x: &()
-        }
-    };
-
-    let _v = r.x.x;
-}
diff --git a/src/test/ui/issues/issue-56031.rs b/src/test/ui/issues/issue-56031.rs
deleted file mode 100644 (file)
index b68f568..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-struct T;
-
-impl for T {}
-//~^ ERROR missing trait in a trait impl
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr
deleted file mode 100644 (file)
index 7ee5bc6..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: missing trait in a trait impl
-  --> $DIR/issue-56031.rs:3:5
-   |
-LL | impl for T {}
-   |     ^
-   |
-help: add a trait here
-   |
-LL | impl Trait for T {}
-   |      +++++
-help: for an inherent impl, drop this `for`
-   |
-LL - impl for T {}
-LL + impl T {}
-   | 
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-57410-1.rs b/src/test/ui/issues/issue-57410-1.rs
deleted file mode 100644 (file)
index d825cb1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-pass
-
-// Originally from #53925.
-// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
-
-#![deny(unreachable_pub)]
-
-mod foo {
-    mod bar {
-        pub struct Bar;
-    }
-
-    pub use self::bar::Bar;
-}
-
-pub use foo::Bar;
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs
deleted file mode 100644 (file)
index ebeb3fe..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// Regression test for #57597.
-//
-// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
-
-// edition:2018
-
-macro_rules! foo1 {
-    ($($($i:ident)?)+) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo2 {
-    ($($($i:ident)?)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo3 {
-    ($($($i:ident)?)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo4 {
-    ($($($($i:ident)?)?)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo5 {
-    ($($($($i:ident)*)?)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo6 {
-    ($($($($i:ident)?)*)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo7 {
-    ($($($($i:ident)?)?)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo8 {
-    ($($($($i:ident)*)*)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo9 {
-    ($($($($i:ident)?)*)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo10 {
-    ($($($($i:ident)?)*)+) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo11 {
-    ($($($($i:ident)+)?)*) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo12 {
-    ($($($($i:ident)+)*)?) => {};
-    //~^ ERROR repetition matches empty token tree
-}
-
-fn main() {
-    foo1!();
-    foo2!();
-    foo3!();
-    foo4!();
-    foo5!();
-    foo6!();
-    foo7!();
-    foo8!();
-    foo9!();
-    foo10!();
-    foo11!();
-    foo12!();
-}
diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr
deleted file mode 100644 (file)
index 0a02ac8..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:8:7
-   |
-LL |     ($($($i:ident)?)+) => {};
-   |       ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:13:7
-   |
-LL |     ($($($i:ident)?)*) => {};
-   |       ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:18:7
-   |
-LL |     ($($($i:ident)?)?) => {};
-   |       ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:23:7
-   |
-LL |     ($($($($i:ident)?)?)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:28:7
-   |
-LL |     ($($($($i:ident)*)?)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:33:7
-   |
-LL |     ($($($($i:ident)?)*)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:38:7
-   |
-LL |     ($($($($i:ident)?)?)*) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:43:7
-   |
-LL |     ($($($($i:ident)*)*)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:48:7
-   |
-LL |     ($($($($i:ident)?)*)*) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:53:7
-   |
-LL |     ($($($($i:ident)?)*)+) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:58:7
-   |
-LL |     ($($($($i:ident)+)?)*) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
-  --> $DIR/issue-57597.rs:63:7
-   |
-LL |     ($($($($i:ident)+)*)?) => {};
-   |       ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 12 previous errors
-
diff --git a/src/test/ui/issues/issue-58319.rs b/src/test/ui/issues/issue-58319.rs
deleted file mode 100644 (file)
index 757307d..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-// run-pass
-fn main() {}
-#[derive(Clone)]
-pub struct Little;
-#[derive(Clone)]
-pub struct Big(
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-    Little,
-);
diff --git a/src/test/ui/issues/issue-59029-1.rs b/src/test/ui/issues/issue-59029-1.rs
deleted file mode 100644 (file)
index 8ab47a4..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(trait_alias)]
-
-trait Svc<Req> { type Res; }
-
-trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
-//~^ ERROR associated type `Res` not found for `Self`
-//~| ERROR associated type `Res` not found for `Self`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59029-1.stderr b/src/test/ui/issues/issue-59029-1.stderr
deleted file mode 100644 (file)
index 53cdb8b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0220]: associated type `Res` not found for `Self`
-  --> $DIR/issue-59029-1.rs:5:52
-   |
-LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
-   |                                                    ^^^ associated type `Res` not found
-
-error[E0220]: associated type `Res` not found for `Self`
-  --> $DIR/issue-59029-1.rs:5:52
-   |
-LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
-   |                                                    ^^^ associated type `Res` not found
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/issues/issue-59508-1.rs b/src/test/ui/issues/issue-59508-1.rs
deleted file mode 100644 (file)
index 6376c42..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![allow(dead_code)]
-#![feature(const_generics_defaults)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions mention that
-// consts come after types and lifetimes when the `const_generics_defaults` feature is enabled.
-// We cannot run rustfix on this test because of the above const generics warning.
-
-struct A;
-
-impl A {
-    pub fn do_things<T, 'a, 'b: 'a>() {
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
-        println!("panic");
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59508-1.stderr b/src/test/ui/issues/issue-59508-1.stderr
deleted file mode 100644 (file)
index df244f0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-59508-1.rs:11:25
-   |
-LL |     pub fn do_things<T, 'a, 'b: 'a>() {
-   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-59508.fixed b/src/test/ui/issues/issue-59508.fixed
deleted file mode 100644 (file)
index b5c60a1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-rustfix
-
-#![allow(dead_code)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
-
-struct A;
-
-impl A {
-    pub fn do_things<'a, 'b: 'a, T>() {
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
-        println!("panic");
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59508.rs b/src/test/ui/issues/issue-59508.rs
deleted file mode 100644 (file)
index 0b39c5d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-rustfix
-
-#![allow(dead_code)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
-
-struct A;
-
-impl A {
-    pub fn do_things<T, 'a, 'b: 'a>() {
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
-        println!("panic");
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-59508.stderr b/src/test/ui/issues/issue-59508.stderr
deleted file mode 100644 (file)
index 33e967c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-59508.rs:10:25
-   |
-LL |     pub fn do_things<T, 'a, 'b: 'a>() {
-   |                     ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs
deleted file mode 100644 (file)
index c63b154..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-pub trait Trait<'a> {
-    type Item;
-}
-
-impl<'a> Trait<'a> for () {
-    type Item = ();
-}
-
-pub fn foo<T, F>(_: T, _: F)
-where
-    T: for<'a> Trait<'a>,
-    F: for<'a> FnMut(<T as Trait<'a>>::Item),
-{
-}
-
-fn main() {
-    foo((), drop)
-    //~^ ERROR type mismatch in function arguments
-    //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
-}
diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr
deleted file mode 100644 (file)
index 34893cd..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-error[E0631]: type mismatch in function arguments
-  --> $DIR/issue-60283.rs:17:13
-   |
-LL |     foo((), drop)
-   |     ---     ^^^^
-   |     |       |
-   |     |       expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
-   |     |       found signature of `fn(()) -> _`
-   |     required by a bound introduced by this call
-   |
-note: required by a bound in `foo`
-  --> $DIR/issue-60283.rs:12:16
-   |
-LL | pub fn foo<T, F>(_: T, _: F)
-   |        --- required by a bound in this
-...
-LL |     F: for<'a> FnMut(<T as Trait<'a>>::Item),
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
-  --> $DIR/issue-60283.rs:17:13
-   |
-LL |     foo((), drop)
-   |     ---     ^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
-   |
-   = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
-note: required by a bound in `std::mem::drop`
-  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub fn drop<T>(_x: T) {}
-   |             ^ required by this bound in `std::mem::drop`
-help: consider further restricting the associated type
-   |
-LL | fn main() where <() as Trait<'_>>::Item: Sized {
-   |           ++++++++++++++++++++++++++++++++++++
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-60662.rs b/src/test/ui/issues/issue-60662.rs
deleted file mode 100644 (file)
index b9faa66..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-// compile-flags: -Z unpretty=hir
-
-#![feature(type_alias_impl_trait)]
-
-trait Animal {}
-
-fn main() {
-    pub type ServeFut = impl Animal;
-}
diff --git a/src/test/ui/issues/issue-60662.stdout b/src/test/ui/issues/issue-60662.stdout
deleted file mode 100644 (file)
index 14a49f2..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-// compile-flags: -Z unpretty=hir
-
-#![feature(type_alias_impl_trait)]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-
-trait Animal { }
-
-fn main() {
-              pub type ServeFut = /*impl Trait*/;
-          }
diff --git a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs
deleted file mode 100644 (file)
index de7d6a0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Issue 61711: A crate pub re-exporting `crate` was causing an
-// infinite loop.
-
-// edition:2018
-// aux-build:xcrate-issue-61711-b.rs
-// compile-flags:--extern xcrate_issue_61711_b
-
-// build-pass
-
-fn f<F: Fn(xcrate_issue_61711_b::Struct)>(_: F) { }
-fn main() { }
diff --git a/src/test/ui/issues/issue-61882-2.rs b/src/test/ui/issues/issue-61882-2.rs
deleted file mode 100644 (file)
index 1209b54..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-struct A<T>(T);
-
-impl A<&'static u8> {
-    fn f() {
-        let x = 0;
-        Self(&x);
-        //~^ ERROR `x` does not live long enough
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-61882-2.stderr b/src/test/ui/issues/issue-61882-2.stderr
deleted file mode 100644 (file)
index 0b8e134..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0597]: `x` does not live long enough
-  --> $DIR/issue-61882-2.rs:6:14
-   |
-LL |         Self(&x);
-   |              ^^
-   |              |
-   |              borrowed value does not live long enough
-   |              this usage requires that `x` is borrowed for `'static`
-LL |
-LL |     }
-   |     - `x` dropped here while still borrowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-61882.rs b/src/test/ui/issues/issue-61882.rs
deleted file mode 100644 (file)
index 013398b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-struct A<T>(T);
-
-impl A<bool> {
-    const B: A<u8> = Self(0);
-    //~^ ERROR mismatched types
-    //~| ERROR mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-61882.stderr b/src/test/ui/issues/issue-61882.stderr
deleted file mode 100644 (file)
index 09ffe8e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-61882.rs:4:27
-   |
-LL |     const B: A<u8> = Self(0);
-   |                           ^ expected `bool`, found integer
-
-error[E0308]: mismatched types
-  --> $DIR/issue-61882.rs:4:22
-   |
-LL |     const B: A<u8> = Self(0);
-   |                      ^^^^^^^ expected `u8`, found `bool`
-   |
-   = note: expected struct `A<u8>`
-              found struct `A<bool>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-63364.rs b/src/test/ui/issues/issue-63364.rs
deleted file mode 100644 (file)
index 5223267..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-fn part(_: u16) -> u32 {
-    1
-}
-
-fn main() {
-    for n in 100_000.. {
-    //~^ ERROR: literal out of range for `u16`
-        let _ = part(n);
-    }
-}
diff --git a/src/test/ui/issues/issue-63364.stderr b/src/test/ui/issues/issue-63364.stderr
deleted file mode 100644 (file)
index 0375359..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: literal out of range for `u16`
-  --> $DIR/issue-63364.rs:6:14
-   |
-LL |     for n in 100_000.. {
-   |              ^^^^^^^
-   |
-   = note: `#[deny(overflowing_literals)]` on by default
-   = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-6596-1.rs b/src/test/ui/issues/issue-6596-1.rs
deleted file mode 100644 (file)
index 25f1d65..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-macro_rules! e {
-    ($inp:ident) => (
-        $nonexistent
-        //~^ ERROR expected expression, found `$`
-    );
-}
-
-fn main() {
-    e!(foo);
-}
diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/issues/issue-6596-1.stderr
deleted file mode 100644 (file)
index 7ab3685..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: expected expression, found `$`
-  --> $DIR/issue-6596-1.rs:3:9
-   |
-LL |         $nonexistent
-   |         ^^^^^^^^^^^^ expected expression
-...
-LL |     e!(foo);
-   |     ------- in this macro invocation
-   |
-   = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-6804.rs b/src/test/ui/issues/issue-6804.rs
deleted file mode 100644 (file)
index 0260caa..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Matching against NaN should result in a warning
-
-#![allow(unused)]
-#![deny(illegal_floating_point_literal_pattern)]
-
-const NAN: f64 = f64::NAN;
-
-fn main() {
-    let x = NAN;
-    match x {
-        NAN => {}, //~ ERROR floating-point types cannot be used
-        //~| WARN this was previously accepted by the compiler but is being phased out
-        _ => {},
-    };
-
-    match [x, 1.0] {
-        [NAN, _] => {}, //~ ERROR floating-point types cannot be used
-        //~| WARN this was previously accepted by the compiler but is being phased out
-        _ => {},
-    };
-}
diff --git a/src/test/ui/issues/issue-6804.stderr b/src/test/ui/issues/issue-6804.stderr
deleted file mode 100644 (file)
index 4e2961e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-6804.rs:11:9
-   |
-LL |         NAN => {},
-   |         ^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-6804.rs:4:9
-   |
-LL | #![deny(illegal_floating_point_literal_pattern)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-6804.rs:17:10
-   |
-LL |         [NAN, _] => {},
-   |          ^^^
-   |
-   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-72455.rs b/src/test/ui/issues/issue-72455.rs
deleted file mode 100644 (file)
index b6c3bb2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// check-pass
-
-pub trait ResultExt {
-    type Ok;
-    fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
-}
-
-impl<O, E> ResultExt for std::result::Result<O, E>
-where
-    E: std::error::Error,
-{
-    type Ok = O;
-    fn err_eprint_and_ignore(self) -> Option<O>
-    where
-        Self: ,
-    {
-        match self {
-            Err(e) => {
-                eprintln!("{}", e);
-                None
-            }
-            Ok(o) => Some(o),
-        }
-    }
-}
-
-fn main() {}
index bf2794eb632b6281358710aa53b372a0ac762481..7b16fa024f8e44122040c497c86e44b921d76ea7 100644 (file)
@@ -5,6 +5,7 @@
 pub unsafe fn g() {
     return;
     if *ptr::null() {}; //~ ERROR unreachable
+    //~| WARNING dereferencing a null pointer
 }
 
 pub fn main() {}
index bb0221ecb86b448342489a288294386ebd84008f..a9bf2bf763d575b09f91b88f3bd30b0ff026a6b7 100644 (file)
@@ -12,5 +12,13 @@ note: the lint level is defined here
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+warning: dereferencing a null pointer
+  --> $DIR/issue-7246.rs:7:8
+   |
+LL |     if *ptr::null() {};
+   |        ^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+   = note: `#[warn(deref_nullptr)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/issues/issue-72574-2.rs
deleted file mode 100644 (file)
index 0ad2db8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-struct Binder(i32, i32, i32);
-
-fn main() {
-    let x = Binder(1, 2, 3);
-    match x {
-        Binder(_a, _x @ ..) => {}
-        _ => {}
-    }
-}
-//~^^^^ ERROR `_x @` is not allowed in a tuple struct
-//~| ERROR: `..` patterns are not allowed here
-//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr
deleted file mode 100644 (file)
index 05650f0..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-error: `_x @` is not allowed in a tuple struct
-  --> $DIR/issue-72574-2.rs:6:20
-   |
-LL |         Binder(_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 |         Binder(_a, ..) => {}
-   |                    ~~
-
-error: `..` patterns are not allowed here
-  --> $DIR/issue-72574-2.rs:6:25
-   |
-LL |         Binder(_a, _x @ ..) => {}
-   |                         ^^
-   |
-   = note: only allowed in tuple, tuple struct, and slice patterns
-
-error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
-  --> $DIR/issue-72574-2.rs:6:16
-   |
-LL | struct Binder(i32, i32, i32);
-   |               ---  ---  --- tuple struct has 3 fields
-...
-LL |         Binder(_a, _x @ ..) => {}
-   |                ^^  ^^^^^^^ expected 3 fields, found 2
-   |
-help: use `_` to explicitly ignore each field
-   |
-LL |         Binder(_a, _x @ .., _) => {}
-   |                           +++
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/issues/issue-73541-1.rs b/src/test/ui/issues/issue-73541-1.rs
deleted file mode 100644 (file)
index 7fb0d6c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// edition:2018
-
-fn main() {
-    'a: loop {
-        async {
-            loop {
-                continue 'a
-                //~^ ERROR use of unreachable label `'a`
-            }
-        };
-    }
-}
diff --git a/src/test/ui/issues/issue-73541-1.stderr b/src/test/ui/issues/issue-73541-1.stderr
deleted file mode 100644 (file)
index 80c1fdf..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0767]: use of unreachable label `'a`
-  --> $DIR/issue-73541-1.rs:7:26
-   |
-LL |     'a: loop {
-   |     -- unreachable label defined here
-...
-LL |                 continue 'a
-   |                          ^^ unreachable label `'a`
-   |
-   = note: labels are unreachable through functions, closures, async blocks and modules
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0767`.
diff --git a/src/test/ui/issues/issue-73886.rs b/src/test/ui/issues/issue-73886.rs
deleted file mode 100644 (file)
index 9c0c87a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let _ = &&[0] as &[_];
-    //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]`
-    let _ = 7u32 as Option<_>;
-    //~^ ERROR non-primitive cast: `u32` as `Option<_>`
-}
diff --git a/src/test/ui/issues/issue-73886.stderr b/src/test/ui/issues/issue-73886.stderr
deleted file mode 100644 (file)
index a6f8ba6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
-  --> $DIR/issue-73886.rs:2:13
-   |
-LL |     let _ = &&[0] as &[_];
-   |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error[E0605]: non-primitive cast: `u32` as `Option<_>`
-  --> $DIR/issue-73886.rs:4:13
-   |
-LL |     let _ = 7u32 as Option<_>;
-   |             ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
-   |
-   = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/issues/issue-74739.rs b/src/test/ui/issues/issue-74739.rs
deleted file mode 100644 (file)
index 0362235..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// compile-flags: -O
-// run-pass
-
-struct Foo {
-    x: i32,
-}
-
-pub fn main() {
-    let mut foo = Foo { x: 42 };
-    let x = &mut foo.x;
-    *x = 13;
-    let y = foo;
-    assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
-}
diff --git a/src/test/ui/issues/issue-811.rs b/src/test/ui/issues/issue-811.rs
deleted file mode 100644 (file)
index f929d38..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// run-fail
-// error-pattern:quux
-// ignore-emscripten no processes
-
-use std::marker::PhantomData;
-
-fn test00_start(ch: Chan<isize>, message: isize) {
-    send(ch, message);
-}
-
-type TaskId = isize;
-type PortId = isize;
-
-struct Chan<T> {
-    task: TaskId,
-    port: PortId,
-    marker: PhantomData<*mut T>,
-}
-
-fn send<T: Send>(_ch: Chan<T>, _data: T) {
-    panic!();
-}
-
-fn main() {
-    panic!("quux");
-}
diff --git a/src/test/ui/issues/issue-8351-1.rs b/src/test/ui/issues/issue-8351-1.rs
deleted file mode 100644 (file)
index 139f027..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-
-enum E {
-    Foo{f: isize},
-    Bar,
-}
-
-pub fn main() {
-    let e = E::Foo{f: 0};
-    match e {
-        E::Foo{f: 1} => panic!(),
-        E::Foo{..} => (),
-        _ => panic!(),
-    }
-}
diff --git a/src/test/ui/issues/issue-8351-2.rs b/src/test/ui/issues/issue-8351-2.rs
deleted file mode 100644 (file)
index bc66cbb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-
-enum E {
-    Foo{f: isize, b: bool},
-    Bar,
-}
-
-pub fn main() {
-    let e = E::Foo{f: 0, b: false};
-    match e {
-        E::Foo{f: 1, b: true} => panic!(),
-        E::Foo{b: false, f: 0} => (),
-        _ => panic!(),
-    }
-}
diff --git a/src/test/ui/issues/issue-86865.rs b/src/test/ui/issues/issue-86865.rs
deleted file mode 100644 (file)
index 01e0a20..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-use std::fmt::Write;
-
-fn main() {
-    println!(b"foo");
-    //~^ ERROR format argument must be a string literal
-    //~| HELP consider removing the leading `b`
-    let mut s = String::new();
-    write!(s, b"foo{}", "bar");
-    //~^ ERROR format argument must be a string literal
-    //~| HELP consider removing the leading `b`
-}
diff --git a/src/test/ui/issues/issue-86865.stderr b/src/test/ui/issues/issue-86865.stderr
deleted file mode 100644 (file)
index eed7553..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: format argument must be a string literal
-  --> $DIR/issue-86865.rs:4:14
-   |
-LL |     println!(b"foo");
-   |              -^^^^^
-   |              |
-   |              help: consider removing the leading `b`
-
-error: format argument must be a string literal
-  --> $DIR/issue-86865.rs:8:15
-   |
-LL |     write!(s, b"foo{}", "bar");
-   |               -^^^^^^^
-   |               |
-   |               help: consider removing the leading `b`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-8827.rs b/src/test/ui/issues/issue-8827.rs
deleted file mode 100644 (file)
index 95be761..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-
-use std::thread;
-use std::sync::mpsc::{channel, Receiver};
-
-fn periodical(n: isize) -> Receiver<bool> {
-    let (chan, port) = channel();
-    thread::spawn(move|| {
-        loop {
-            for _ in 1..n {
-                match chan.send(false) {
-                    Ok(()) => {}
-                    Err(..) => break,
-                }
-            }
-            match chan.send(true) {
-                Ok(()) => {}
-                Err(..) => break
-            }
-        }
-    });
-    return port;
-}
-
-fn integers() -> Receiver<isize> {
-    let (chan, port) = channel();
-    thread::spawn(move|| {
-        let mut i = 1;
-        loop {
-            match chan.send(i) {
-                Ok(()) => {}
-                Err(..) => break,
-            }
-            i = i + 1;
-        }
-    });
-    return port;
-}
-
-fn main() {
-    let ints = integers();
-    let threes = periodical(3);
-    let fives = periodical(5);
-    for _ in 1..100 {
-        match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) {
-            (_, true, true) => println!("FizzBuzz"),
-            (_, true, false) => println!("Fizz"),
-            (_, false, true) => println!("Buzz"),
-            (i, false, false) => println!("{}", i)
-        }
-    }
-}
diff --git a/src/test/ui/issues/issue-9396.rs b/src/test/ui/issues/issue-9396.rs
deleted file mode 100644 (file)
index 3e7e9a5..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-#![allow(unused_must_use)]
-#![allow(deprecated)]
-// ignore-emscripten no threads support
-
-use std::sync::mpsc::{TryRecvError, channel};
-use std::thread;
-
-pub fn main() {
-    let (tx, rx) = channel();
-    let t = thread::spawn(move||{
-        thread::sleep_ms(10);
-        tx.send(()).unwrap();
-    });
-    loop {
-        match rx.try_recv() {
-            Ok(()) => break,
-            Err(TryRecvError::Empty) => {}
-            Err(TryRecvError::Disconnected) => unreachable!()
-        }
-    }
-    t.join();
-}
diff --git a/src/test/ui/lambda-var-hygiene.rs b/src/test/ui/lambda-var-hygiene.rs
deleted file mode 100644 (file)
index bf06765..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-// shouldn't affect evaluation of $ex:
-macro_rules! bad_macro {
-    ($ex:expr) => ({(|_x| { $ex }) (9) })
-}
-
-fn takes_x(_x : isize) {
-    assert_eq!(bad_macro!(_x),8);
-}
-fn main() {
-    takes_x(8);
-}
diff --git a/src/test/ui/lang-items/issue-19660.rs b/src/test/ui/lang-items/issue-19660.rs
new file mode 100644 (file)
index 0000000..400ac31
--- /dev/null
@@ -0,0 +1,15 @@
+// error-pattern: requires `copy` lang_item
+
+#![feature(lang_items, start, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized { }
+
+struct S;
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    let _ = S;
+    0
+}
diff --git a/src/test/ui/lang-items/issue-19660.stderr b/src/test/ui/lang-items/issue-19660.stderr
new file mode 100644 (file)
index 0000000..f5d903f
--- /dev/null
@@ -0,0 +1,4 @@
+error: requires `copy` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lang-items/issue-31076.rs b/src/test/ui/lang-items/issue-31076.rs
new file mode 100644 (file)
index 0000000..cdb196d
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized {}
+
+#[lang="add"]
+trait Add<T> {}
+
+impl Add<i32> for i32 {}
+
+fn main() {
+    let x = 5 + 6;
+    //~^ ERROR cannot add `i32` to `{integer}`
+    let y = 5i32 + 6i32;
+    //~^ ERROR cannot add `i32` to `i32`
+}
diff --git a/src/test/ui/lang-items/issue-31076.stderr b/src/test/ui/lang-items/issue-31076.stderr
new file mode 100644 (file)
index 0000000..ac0d9dc
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0369]: cannot add `i32` to `{integer}`
+  --> $DIR/issue-31076.rs:13:15
+   |
+LL |     let x = 5 + 6;
+   |             - ^ - i32
+   |             |
+   |             {integer}
+
+error[E0369]: cannot add `i32` to `i32`
+  --> $DIR/issue-31076.rs:15:18
+   |
+LL |     let y = 5i32 + 6i32;
+   |             ---- ^ ---- i32
+   |             |
+   |             i32
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/lang-items/required-lang-item.rs b/src/test/ui/lang-items/required-lang-item.rs
new file mode 100644 (file)
index 0000000..3b17c5b
--- /dev/null
@@ -0,0 +1,11 @@
+// build-fail
+
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang="copy"] pub trait Copy { }
+#[lang="sized"] pub trait Sized { }
+
+// error-pattern:requires `start` lang_item
+
+fn main() {}
diff --git a/src/test/ui/lang-items/required-lang-item.stderr b/src/test/ui/lang-items/required-lang-item.stderr
new file mode 100644 (file)
index 0000000..83764a9
--- /dev/null
@@ -0,0 +1,4 @@
+error: requires `start` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/legacy-const-generics-bad.rs b/src/test/ui/legacy-const-generics-bad.rs
deleted file mode 100644 (file)
index 538eee3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// aux-build:legacy-const-generics.rs
-
-extern crate legacy_const_generics;
-
-fn foo<const N: usize>() {
-    let a = 1;
-    legacy_const_generics::foo(0, a, 2);
-    //~^ ERROR attempt to use a non-constant value in a constant
-
-    legacy_const_generics::foo(0, N, 2);
-
-    legacy_const_generics::foo(0, N + 1, 2);
-    //~^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
diff --git a/src/test/ui/legacy-const-generics-bad.stderr b/src/test/ui/legacy-const-generics-bad.stderr
deleted file mode 100644 (file)
index 3c78dd6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/legacy-const-generics-bad.rs:7:35
-   |
-LL |     let a = 1;
-   |     ----- help: consider using `const` instead of `let`: `const a`
-LL |     legacy_const_generics::foo(0, a, 2);
-   |                                   ^ non-constant value
-
-error: generic parameters may not be used in const operations
-  --> $DIR/legacy-const-generics-bad.rs:12:35
-   |
-LL |     legacy_const_generics::foo(0, N + 1, 2);
-   |                                   ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/legacy-const-generics.rs b/src/test/ui/legacy-const-generics.rs
deleted file mode 100644 (file)
index 9abc72d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// aux-build:legacy-const-generics.rs
-// run-pass
-
-#![feature(rustc_attrs)]
-
-extern crate legacy_const_generics;
-
-#[rustc_legacy_const_generics(1)]
-pub fn bar<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
-    [x, Y, z]
-}
-
-fn main() {
-    assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]);
-    assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]);
-    // FIXME: Only works cross-crate
-    //assert_eq!(bar(0, 1, 2), [0, 1, 2]);
-}
diff --git a/src/test/ui/lifetimes/issue-26638.rs b/src/test/ui/lifetimes/issue-26638.rs
new file mode 100644 (file)
index 0000000..72fe428
--- /dev/null
@@ -0,0 +1,10 @@
+fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_3() -> &str { unimplemented!() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-26638.stderr b/src/test/ui/lifetimes/issue-26638.stderr
new file mode 100644 (file)
index 0000000..bb7cdcb
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:1:62
+   |
+LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
+   |                     ------------------------------------     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
+   |              ++++                                                 ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:4:40
+   |
+LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+   |                                        ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+help: consider using the `'static` lifetime
+   |
+LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() }
+   |                                        ~~~~~~~~
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-26638.rs:7:22
+   |
+LL | fn parse_type_3() -> &str { unimplemented!() }
+   |                      ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL | fn parse_type_3() -> &'static str { unimplemented!() }
+   |                      ~~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
index 38c5487183ca1bfa494fdf22ba7e96bebeea0d68..d9673faa2142e4c5a226143f38a3308f67475ee1 100644 (file)
@@ -4,10 +4,12 @@ mod foo {
 #![allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 
 #[allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 const BAR: f64 = 0.000001;
 
 }
@@ -15,5 +17,6 @@ mod foo {
 #[allow(uncommon_codepoints)]
 //~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 //~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
+//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes]
 fn main() {
 }
index 83bea0412ffd52e794962ff65be131f61c820bfe..8fb06df2a481a68297e4b9ff65639fdd632f09e7 100644 (file)
@@ -11,13 +11,13 @@ LL | #![deny(uncommon_codepoints, unused_attributes)]
    |                              ^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:8:9
+  --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:15:9
+  --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
@@ -29,16 +29,34 @@ LL | #![allow(uncommon_codepoints)]
    |          ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:8:9
+  --> $DIR/crate_level_only_lint.rs:9:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: allow(uncommon_codepoints) is ignored unless specified at crate level
-  --> $DIR/crate_level_only_lint.rs:15:9
+  --> $DIR/crate_level_only_lint.rs:17:9
    |
 LL | #[allow(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:4:10
+   |
+LL | #![allow(uncommon_codepoints)]
+   |          ^^^^^^^^^^^^^^^^^^^
+
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:9:9
+   |
+LL | #[allow(uncommon_codepoints)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: allow(uncommon_codepoints) is ignored unless specified at crate level
+  --> $DIR/crate_level_only_lint.rs:17:9
+   |
+LL | #[allow(uncommon_codepoints)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
index 7d8a398181493b16e1edebef0a3e2739985a38bb..b12fd72da74946bc5355159eb03887cf8ae4339b 100644 (file)
 //~| WARNING previously accepted by the compiler
 //~| ERROR incompatible with previous
 //~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
+//~| ERROR incompatible with previous
+//~| WARNING previously accepted by the compiler
 fn main() {}
index d8c09e6526a2d6f340b6114792230a7556670730..214e949c11a748990d8b906b48c2b82414d1f3a4 100644 (file)
@@ -75,5 +75,41 @@ LL | #[allow(nonstandard_style)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
-error: aborting due to 6 previous errors
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: allow(nonstandard_style) incompatible with previous forbid
+  --> $DIR/forbid-group-group-2.rs:7:9
+   |
+LL | #![forbid(warnings)]
+   |           -------- `forbid` level set here
+...
+LL | #[allow(nonstandard_style)]
+   |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/lint/issue-14837.rs b/src/test/ui/lint/issue-14837.rs
new file mode 100644 (file)
index 0000000..a83bc41
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+// pretty-expanded FIXME #23616
+
+#[deny(dead_code)]
+pub enum Foo {
+    Bar {
+        baz: isize
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/lint/issue-57410-1.rs b/src/test/ui/lint/issue-57410-1.rs
new file mode 100644 (file)
index 0000000..d825cb1
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+// Originally from #53925.
+// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
+
+#![deny(unreachable_pub)]
+
+mod foo {
+    mod bar {
+        pub struct Bar;
+    }
+
+    pub use self::bar::Bar;
+}
+
+pub use foo::Bar;
+
+fn main() {}
diff --git a/src/test/ui/lint/issue-63364.rs b/src/test/ui/lint/issue-63364.rs
new file mode 100644 (file)
index 0000000..5223267
--- /dev/null
@@ -0,0 +1,10 @@
+fn part(_: u16) -> u32 {
+    1
+}
+
+fn main() {
+    for n in 100_000.. {
+    //~^ ERROR: literal out of range for `u16`
+        let _ = part(n);
+    }
+}
diff --git a/src/test/ui/lint/issue-63364.stderr b/src/test/ui/lint/issue-63364.stderr
new file mode 100644 (file)
index 0000000..0375359
--- /dev/null
@@ -0,0 +1,11 @@
+error: literal out of range for `u16`
+  --> $DIR/issue-63364.rs:6:14
+   |
+LL |     for n in 100_000.. {
+   |              ^^^^^^^
+   |
+   = note: `#[deny(overflowing_literals)]` on by default
+   = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
+
+error: aborting due to previous error
+
index b08fbf6f845f88d2b30656db5b132104e9e0c3cd..3ee55ba96b1378746cd26726d543a88b08108b40 100644 (file)
@@ -13,4 +13,5 @@ macro_rules! evil {
 
 fn main() {
     println!("{}", evil!(*(0 as *const u8)));
+    //~^ WARNING dereferencing a null pointer
 }
index e31c003985ed8e606082245760b56fd0a07650a7..ba425ceb442b216c988b165e2f5e8755651cffcc 100644 (file)
@@ -10,5 +10,13 @@ note: the lint level is defined here
 LL | #![forbid(unsafe_code)]
    |           ^^^^^^^^^^^
 
-error: aborting due to previous error
+warning: dereferencing a null pointer
+  --> $DIR/lint-forbid-internal-unsafe.rs:15:26
+   |
+LL |     println!("{}", evil!(*(0 as *const u8)));
+   |                          ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+   = note: `#[warn(deref_nullptr)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
 
index 81a3427a10274b223cd68fe389c6bd2c74696821..ed8e7ddddc5977f370f343b0555b534727db2e18 100644 (file)
@@ -1,6 +1,7 @@
 #![deny(uncommon_codepoints)]
 
 const µ: f64 = 0.000001; //~ ERROR identifier contains uncommon Unicode codepoints
+//~| WARNING should have an upper case name
 
 fn dijkstra() {} //~ ERROR identifier contains uncommon Unicode codepoints
 
index d435282a6e855cca8c9b571bb9d59113da71e33d..0533da03068ae040d1802b1f8a0d4f6b64ad88dc 100644 (file)
@@ -11,16 +11,24 @@ LL | #![deny(uncommon_codepoints)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: identifier contains uncommon Unicode codepoints
-  --> $DIR/lint-uncommon-codepoints.rs:5:4
+  --> $DIR/lint-uncommon-codepoints.rs:6:4
    |
 LL | fn dijkstra() {}
    |    ^^^^^^^
 
 error: identifier contains uncommon Unicode codepoints
-  --> $DIR/lint-uncommon-codepoints.rs:8:9
+  --> $DIR/lint-uncommon-codepoints.rs:9:9
    |
 LL |     let ㇻㇲㇳ = "rust";
    |         ^^^^^^
 
-error: aborting due to 3 previous errors
+warning: constant `µ` should have an upper case name
+  --> $DIR/lint-uncommon-codepoints.rs:3:7
+   |
+LL | const µ: f64 = 0.000001;
+   |       ^ help: convert the identifier to upper case: `Μ`
+   |
+   = note: `#[warn(non_upper_case_globals)]` on by default
+
+error: aborting due to 3 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/lint/unnecessary-extern-crate.rs b/src/test/ui/lint/unnecessary-extern-crate.rs
new file mode 100644 (file)
index 0000000..67eaaf4
--- /dev/null
@@ -0,0 +1,71 @@
+// edition:2018
+
+#![deny(unused_extern_crates)]
+#![feature(test, rustc_private, crate_visibility_modifier)]
+
+extern crate libc;
+//~^ ERROR unused extern crate
+//~| HELP remove
+extern crate libc as x;
+//~^ ERROR unused extern crate
+//~| HELP remove
+
+extern crate proc_macro;
+
+#[macro_use]
+extern crate test;
+
+pub extern crate test as y;
+
+pub extern crate alloc;
+
+pub(crate) extern crate alloc as a;
+
+crate extern crate alloc as b;
+
+mod foo {
+    pub(in crate::foo) extern crate alloc as c;
+
+    pub(super) extern crate alloc as d;
+
+    extern crate libc;
+    //~^ ERROR unused extern crate
+    //~| HELP remove
+
+    extern crate libc as x;
+    //~^ ERROR unused extern crate
+    //~| HELP remove
+
+    pub extern crate test;
+
+    pub extern crate test as y;
+
+    mod bar {
+        extern crate libc;
+        //~^ ERROR unused extern crate
+        //~| HELP remove
+
+        extern crate libc as x;
+        //~^ ERROR unused extern crate
+        //~| HELP remove
+
+        pub(in crate::foo::bar) extern crate alloc as e;
+
+        fn dummy() {
+            e::string::String::new();
+        }
+    }
+
+    fn dummy() {
+        c::string::String::new();
+        d::string::String::new();
+    }
+}
+
+
+fn main() {
+    a::string::String::new();
+    b::string::String::new();
+
+    proc_macro::TokenStream::new();
+}
diff --git a/src/test/ui/lint/unnecessary-extern-crate.stderr b/src/test/ui/lint/unnecessary-extern-crate.stderr
new file mode 100644 (file)
index 0000000..14ba9d0
--- /dev/null
@@ -0,0 +1,44 @@
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:6:1
+   |
+LL | extern crate libc;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: the lint level is defined here
+  --> $DIR/unnecessary-extern-crate.rs:3:9
+   |
+LL | #![deny(unused_extern_crates)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:9:1
+   |
+LL | extern crate libc as x;
+   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:31:5
+   |
+LL |     extern crate libc;
+   |     ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:35:5
+   |
+LL |     extern crate libc as x;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:44:9
+   |
+LL |         extern crate libc;
+   |         ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+  --> $DIR/unnecessary-extern-crate.rs:48:9
+   |
+LL |         extern crate libc as x;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 6 previous errors
+
index ecd618eae8b0743465061f0e8cb06b83979d9149..b2e6d1aeb3f500243149f1d05819d4d134e76a15 100644 (file)
@@ -1,11 +1,8 @@
-warning: unused macro definition
-  --> $DIR/issue-70041.rs:4:1
+warning: unused macro definition: `regex`
+  --> $DIR/issue-70041.rs:4:14
    |
-LL | / macro_rules! regex {
-LL | |
-LL | |     () => {};
-LL | | }
-   | |_^
+LL | macro_rules! regex {
+   |              ^^^^^
    |
    = note: `#[warn(unused_macros)]` on by default
 
index 6812a1d8f631a66301e1404786768e0a880e099a..59db35b4111830cdd7f47f06ec70dfac7fff7fdc 100644 (file)
@@ -1,10 +1,8 @@
-error: unused macro definition
-  --> $DIR/unused-macro-rules.rs:4:1
+error: unused macro definition: `unused`
+  --> $DIR/unused-macro-rules.rs:4:14
    |
-LL | / macro_rules! unused {
-LL | |     () => {};
-LL | | }
-   | |_^
+LL | macro_rules! unused {
+   |              ^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/unused-macro-rules.rs:1:9
@@ -12,26 +10,17 @@ note: the lint level is defined here
 LL | #![deny(unused_macros)]
    |         ^^^^^^^^^^^^^
 
-error: unused macro definition
-  --> $DIR/unused-macro-rules.rs:11:9
+error: unused macro definition: `m`
+  --> $DIR/unused-macro-rules.rs:11:22
    |
-LL | /         macro_rules! m {
-LL | |             () => {};
-LL | |         }
-   | |_________^
-...
-LL |   create_macro!();
-   |   --------------- in this macro invocation
-   |
-   = note: this error originates in the macro `create_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+LL |         macro_rules! m {
+   |                      ^
 
-error: unused macro definition
-  --> $DIR/unused-macro-rules.rs:24:5
+error: unused macro definition: `unused`
+  --> $DIR/unused-macro-rules.rs:24:18
    |
-LL | /     macro_rules! unused {
-LL | |         () => {};
-LL | |     }
-   | |_____^
+LL |     macro_rules! unused {
+   |                  ^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/unused-macro-rules.rs:23:12
index f5eb76179bf4bbbafc5037ec49045b61a499f1f7..1a73279ed6dbdcc517f3a6c3acd613511ecdbd7e 100644 (file)
@@ -1,10 +1,8 @@
-error: unused macro definition
-  --> $DIR/unused-macro.rs:5:1
+error: unused macro definition: `unused`
+  --> $DIR/unused-macro.rs:5:7
    |
-LL | / macro unused {
-LL | |     () => {}
-LL | | }
-   | |_^
+LL | macro unused {
+   |       ^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/unused-macro.rs:2:9
@@ -12,13 +10,11 @@ note: the lint level is defined here
 LL | #![deny(unused_macros)]
    |         ^^^^^^^^^^^^^
 
-error: unused macro definition
-  --> $DIR/unused-macro.rs:15:5
+error: unused macro definition: `unused`
+  --> $DIR/unused-macro.rs:15:11
    |
-LL | /     macro unused {
-LL | |         () => {}
-LL | |     }
-   | |_____^
+LL |     macro unused {
+   |           ^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/unused-macro.rs:14:12
@@ -26,13 +22,11 @@ note: the lint level is defined here
 LL |     #[deny(unused_macros)]
    |            ^^^^^^^^^^^^^
 
-error: unused macro definition
-  --> $DIR/unused-macro.rs:21:5
+error: unused macro definition: `unused`
+  --> $DIR/unused-macro.rs:21:22
    |
-LL | /     pub(crate) macro unused {
-LL | |         () => {}
-LL | |     }
-   | |_____^
+LL |     pub(crate) macro unused {
+   |                      ^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lint/warn-ctypes-inhibit.rs b/src/test/ui/lint/warn-ctypes-inhibit.rs
new file mode 100644 (file)
index 0000000..15d8b09
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![allow(dead_code)]
+// compile-flags:-D improper-ctypes
+
+// pretty-expanded FIXME #23616
+#![allow(improper_ctypes)]
+
+mod libc {
+    extern "C" {
+        pub fn malloc(size: isize) -> *const u8;
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/llvm-asm/issue-23458.rs b/src/test/ui/llvm-asm/issue-23458.rs
new file mode 100644 (file)
index 0000000..d640828
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+// compile-flags: -Ccodegen-units=1
+// build-fail
+// only-x86_64
+
+fn main() {
+    unsafe {
+        llvm_asm!("int $3"); //~ ERROR too few operands for instruction
+                             //~| ERROR invalid operand in inline asm
+    }
+}
diff --git a/src/test/ui/llvm-asm/issue-23458.stderr b/src/test/ui/llvm-asm/issue-23458.stderr
new file mode 100644 (file)
index 0000000..69e458f
--- /dev/null
@@ -0,0 +1,20 @@
+error: invalid operand in inline asm: 'int $3'
+  --> $DIR/issue-23458.rs:9:9
+   |
+LL |         llvm_asm!("int $3");
+   |         ^
+
+error: too few operands for instruction
+  --> $DIR/issue-23458.rs:9:9
+   |
+LL |         llvm_asm!("int $3");
+   |         ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     int 
+   |     ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/llvm-asm/issue-37366.rs b/src/test/ui/llvm-asm/issue-37366.rs
new file mode 100644 (file)
index 0000000..acc2f3e
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+// ignore-emscripten
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+macro_rules! interrupt_handler {
+    () => {
+        unsafe fn _interrupt_handler() {
+            llvm_asm!("pop  eax" :::: "intel");
+        }
+    }
+}
+interrupt_handler!{}
+
+fn main() {}
diff --git a/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs b/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.rs
new file mode 100644 (file)
index 0000000..d9fe7ca
--- /dev/null
@@ -0,0 +1,27 @@
+// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
+
+// build-fail
+// ignore-emscripten
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+macro_rules! fake_jump {
+    ($id:expr) => {
+        unsafe {
+            llvm_asm!(
+            "
+            jmp $0
+            lea eax, [ebx]
+            xor eax, 0xDEADBEEF
+            retn
+            $0:
+            "::"0"($id)::"volatile", "intel");
+        }
+    };
+}
+
+fn main() {
+    fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr b/src/test/ui/llvm-asm/issue-53787-inline-assembler-macro.stderr
new file mode 100644 (file)
index 0000000..fd755e3
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/issue-53787-inline-assembler-macro.rs:25:16
+   |
+LL |     fake_jump!("FirstFunc");
+   |                ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/long-while.rs b/src/test/ui/long-while.rs
deleted file mode 100644 (file)
index 529cca7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![allow(unused_variables)]
-
-pub fn main() {
-    let mut i: isize = 0;
-    while i < 1000000 {
-        i += 1;
-        let x = 3;
-    }
-}
diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.rs b/src/test/ui/lto-and-no-bitcode-in-rlib.rs
deleted file mode 100644 (file)
index f381240..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// compile-flags: -C lto -C embed-bitcode=no
-
-fn main() {}
diff --git a/src/test/ui/lto-and-no-bitcode-in-rlib.stderr b/src/test/ui/lto-and-no-bitcode-in-rlib.stderr
deleted file mode 100644 (file)
index 11e370e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: options `-C embed-bitcode=no` and `-C lto` are incompatible
-
diff --git a/src/test/ui/lto-duplicate-symbols.rs b/src/test/ui/lto-duplicate-symbols.rs
deleted file mode 100644 (file)
index 268cf26..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// build-fail
-// aux-build:lto-duplicate-symbols1.rs
-// aux-build:lto-duplicate-symbols2.rs
-// error-pattern:Linking globals named 'foo': symbol multiply defined!
-// compile-flags: -C lto
-// no-prefer-dynamic
-
-extern crate lto_duplicate_symbols1;
-extern crate lto_duplicate_symbols2;
-
-fn main() {}
diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr
deleted file mode 100644 (file)
index e4de04e..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-warning: Linking globals named 'foo': symbol multiply defined!
-
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o": 
-
-error: aborting due to previous error; 1 warning emitted
-
diff --git a/src/test/ui/lto-many-codegen-units.rs b/src/test/ui/lto-many-codegen-units.rs
deleted file mode 100644 (file)
index f0f461f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// run-pass
-// compile-flags: -C lto -C codegen-units=8
-// no-prefer-dynamic
-
-fn main() {
-}
diff --git a/src/test/ui/lto-opt-level-s.rs b/src/test/ui/lto-opt-level-s.rs
deleted file mode 100644 (file)
index a7d9d50..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags: -Clinker-plugin-lto -Copt-level=s
-// build-pass
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
diff --git a/src/test/ui/lto-opt-level-z.rs b/src/test/ui/lto-opt-level-z.rs
deleted file mode 100644 (file)
index bf1f5e2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags: -Clinker-plugin-lto -Copt-level=z
-// build-pass
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
diff --git a/src/test/ui/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto-rustc-loads-linker-plugin.rs
deleted file mode 100644 (file)
index 6ef1d45..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// compile-flags: -C lto
-// aux-build:lto-rustc-loads-linker-plugin.rs
-// run-pass
-// no-prefer-dynamic
-
-// This test ensures that if a dependency was compiled with
-// `-Clinker-plugin-lto` then we can compile with `-Clto` and still link against
-// that upstream rlib. This should work because LTO implies we're not actually
-// linking against upstream rlibs since we're generating the object code
-// locally. This test will fail if rustc can't find bytecode in rlibs compiled
-// with `-Clinker-plugin-lto`.
-
-extern crate lto_rustc_loads_linker_plugin;
-
-fn main() {
-    lto_rustc_loads_linker_plugin::foo();
-}
diff --git a/src/test/ui/lto-still-runs-thread-dtors.rs b/src/test/ui/lto-still-runs-thread-dtors.rs
deleted file mode 100644 (file)
index 1c7368b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// run-pass
-// compile-flags: -C lto
-// no-prefer-dynamic
-// ignore-emscripten no threads support
-// revisions: mir thir
-// [thir]compile-flags: -Zthir-unsafeck
-
-use std::thread;
-
-static mut HIT: usize = 0;
-
-thread_local!(static A: Foo = Foo);
-
-struct Foo;
-
-impl Drop for Foo {
-    fn drop(&mut self) {
-        unsafe {
-            HIT += 1;
-        }
-    }
-}
-
-fn main() {
-    unsafe {
-        assert_eq!(HIT, 0);
-        thread::spawn(|| {
-            assert_eq!(HIT, 0);
-            A.with(|_| ());
-            assert_eq!(HIT, 0);
-        }).join().unwrap();
-        assert_eq!(HIT, 1);
-    }
-}
diff --git a/src/test/ui/lto-thin-rustc-loads-linker-plugin.rs b/src/test/ui/lto-thin-rustc-loads-linker-plugin.rs
deleted file mode 100644 (file)
index 4d54ce3..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile-flags: -C lto=thin
-// aux-build:lto-rustc-loads-linker-plugin.rs
-// run-pass
-// no-prefer-dynamic
-
-// Same as the adjacent `lto-thin-rustc-loads-linker-plugin.rs` test, only with
-// ThinLTO.
-
-extern crate lto_rustc_loads_linker_plugin;
-
-fn main() {
-    lto_rustc_loads_linker_plugin::foo();
-}
diff --git a/src/test/ui/lto/all-crates.rs b/src/test/ui/lto/all-crates.rs
new file mode 100644 (file)
index 0000000..e910b2a
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+
+// compile-flags: -Clto=thin
+// no-prefer-dynamic
+
+fn main() {
+    println!("hello!");
+}
diff --git a/src/test/ui/lto/auxiliary/dylib.rs b/src/test/ui/lto/auxiliary/dylib.rs
new file mode 100644 (file)
index 0000000..e8b7f8f
--- /dev/null
@@ -0,0 +1,6 @@
+// compile-flags: -Z thinlto -C codegen-units=8
+
+#[inline]
+pub fn foo(b: u8) {
+    b.to_string();
+}
diff --git a/src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs b/src/test/ui/lto/auxiliary/lto-duplicate-symbols1.rs
new file mode 100644 (file)
index 0000000..ec6d056
--- /dev/null
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern "C" fn foo() {}
diff --git a/src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs b/src/test/ui/lto/auxiliary/lto-duplicate-symbols2.rs
new file mode 100644 (file)
index 0000000..ec6d056
--- /dev/null
@@ -0,0 +1,6 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern "C" fn foo() {}
diff --git a/src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs
new file mode 100644 (file)
index 0000000..d24375b
--- /dev/null
@@ -0,0 +1,6 @@
+// compile-flags: -Clinker-plugin-lto
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
diff --git a/src/test/ui/lto/auxiliary/msvc-imp-present.rs b/src/test/ui/lto/auxiliary/msvc-imp-present.rs
new file mode 100644 (file)
index 0000000..933af05
--- /dev/null
@@ -0,0 +1,11 @@
+// no-prefer-dynamic
+// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic
+
+#![crate_type = "rlib"]
+#![crate_type = "dylib"]
+
+pub static A: u32 = 43;
+
+pub mod a {
+    pub static A: u32 = 43;
+}
diff --git a/src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs b/src/test/ui/lto/auxiliary/thin-lto-inlines-aux.rs
new file mode 100644 (file)
index 0000000..5fd3f19
--- /dev/null
@@ -0,0 +1,7 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn bar() -> u32 {
+    3
+}
diff --git a/src/test/ui/lto/dylib-works.rs b/src/test/ui/lto/dylib-works.rs
new file mode 100644 (file)
index 0000000..9e0782b
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+// aux-build:dylib.rs
+
+extern crate dylib;
+
+fn main() {
+    dylib::foo(1);
+}
diff --git a/src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs b/src/test/ui/lto/lto-and-no-bitcode-in-rlib.rs
new file mode 100644 (file)
index 0000000..f381240
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags: -C lto -C embed-bitcode=no
+
+fn main() {}
diff --git a/src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr b/src/test/ui/lto/lto-and-no-bitcode-in-rlib.stderr
new file mode 100644 (file)
index 0000000..11e370e
--- /dev/null
@@ -0,0 +1,2 @@
+error: options `-C embed-bitcode=no` and `-C lto` are incompatible
+
diff --git a/src/test/ui/lto/lto-duplicate-symbols.rs b/src/test/ui/lto/lto-duplicate-symbols.rs
new file mode 100644 (file)
index 0000000..268cf26
--- /dev/null
@@ -0,0 +1,11 @@
+// build-fail
+// aux-build:lto-duplicate-symbols1.rs
+// aux-build:lto-duplicate-symbols2.rs
+// error-pattern:Linking globals named 'foo': symbol multiply defined!
+// compile-flags: -C lto
+// no-prefer-dynamic
+
+extern crate lto_duplicate_symbols1;
+extern crate lto_duplicate_symbols2;
+
+fn main() {}
diff --git a/src/test/ui/lto/lto-duplicate-symbols.stderr b/src/test/ui/lto/lto-duplicate-symbols.stderr
new file mode 100644 (file)
index 0000000..e4de04e
--- /dev/null
@@ -0,0 +1,6 @@
+warning: Linking globals named 'foo': symbol multiply defined!
+
+error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o": 
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/lto/lto-many-codegen-units.rs b/src/test/ui/lto/lto-many-codegen-units.rs
new file mode 100644 (file)
index 0000000..f0f461f
--- /dev/null
@@ -0,0 +1,6 @@
+// run-pass
+// compile-flags: -C lto -C codegen-units=8
+// no-prefer-dynamic
+
+fn main() {
+}
diff --git a/src/test/ui/lto/lto-opt-level-s.rs b/src/test/ui/lto/lto-opt-level-s.rs
new file mode 100644 (file)
index 0000000..a7d9d50
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: -Clinker-plugin-lto -Copt-level=s
+// build-pass
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
diff --git a/src/test/ui/lto/lto-opt-level-z.rs b/src/test/ui/lto/lto-opt-level-z.rs
new file mode 100644 (file)
index 0000000..bf1f5e2
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: -Clinker-plugin-lto -Copt-level=z
+// build-pass
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
diff --git a/src/test/ui/lto/lto-rustc-loads-linker-plugin.rs b/src/test/ui/lto/lto-rustc-loads-linker-plugin.rs
new file mode 100644 (file)
index 0000000..6ef1d45
--- /dev/null
@@ -0,0 +1,17 @@
+// compile-flags: -C lto
+// aux-build:lto-rustc-loads-linker-plugin.rs
+// run-pass
+// no-prefer-dynamic
+
+// This test ensures that if a dependency was compiled with
+// `-Clinker-plugin-lto` then we can compile with `-Clto` and still link against
+// that upstream rlib. This should work because LTO implies we're not actually
+// linking against upstream rlibs since we're generating the object code
+// locally. This test will fail if rustc can't find bytecode in rlibs compiled
+// with `-Clinker-plugin-lto`.
+
+extern crate lto_rustc_loads_linker_plugin;
+
+fn main() {
+    lto_rustc_loads_linker_plugin::foo();
+}
diff --git a/src/test/ui/lto/lto-still-runs-thread-dtors.rs b/src/test/ui/lto/lto-still-runs-thread-dtors.rs
new file mode 100644 (file)
index 0000000..1c7368b
--- /dev/null
@@ -0,0 +1,34 @@
+// run-pass
+// compile-flags: -C lto
+// no-prefer-dynamic
+// ignore-emscripten no threads support
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+use std::thread;
+
+static mut HIT: usize = 0;
+
+thread_local!(static A: Foo = Foo);
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        unsafe {
+            HIT += 1;
+        }
+    }
+}
+
+fn main() {
+    unsafe {
+        assert_eq!(HIT, 0);
+        thread::spawn(|| {
+            assert_eq!(HIT, 0);
+            A.with(|_| ());
+            assert_eq!(HIT, 0);
+        }).join().unwrap();
+        assert_eq!(HIT, 1);
+    }
+}
diff --git a/src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs b/src/test/ui/lto/lto-thin-rustc-loads-linker-plugin.rs
new file mode 100644 (file)
index 0000000..4d54ce3
--- /dev/null
@@ -0,0 +1,13 @@
+// compile-flags: -C lto=thin
+// aux-build:lto-rustc-loads-linker-plugin.rs
+// run-pass
+// no-prefer-dynamic
+
+// Same as the adjacent `lto-thin-rustc-loads-linker-plugin.rs` test, only with
+// ThinLTO.
+
+extern crate lto_rustc_loads_linker_plugin;
+
+fn main() {
+    lto_rustc_loads_linker_plugin::foo();
+}
diff --git a/src/test/ui/lto/msvc-imp-present.rs b/src/test/ui/lto/msvc-imp-present.rs
new file mode 100644 (file)
index 0000000..5498afb
--- /dev/null
@@ -0,0 +1,22 @@
+// run-pass
+
+// aux-build:msvc-imp-present.rs
+// compile-flags: -Z thinlto -C codegen-units=8
+// no-prefer-dynamic
+
+// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name`
+// for all exported statics. This is done because we apply `dllimport` to all
+// imported constants and this allows everything to actually link correctly.
+//
+// The ThinLTO passes aggressively remove symbols if they can, and this test
+// asserts that the ThinLTO passes don't remove these compiler-generated
+// `_imp_*` symbols. The external library that we link in here is compiled with
+// ThinLTO and multiple codegen units and has a few exported constants. Note
+// that we also namely compile the library as both a dylib and an rlib, but we
+// link the rlib to ensure that we assert those generated symbols exist.
+
+extern crate msvc_imp_present as bar;
+
+fn main() {
+    println!("{}", bar::A);
+}
diff --git a/src/test/ui/lto/thin-lto-global-allocator.rs b/src/test/ui/lto/thin-lto-global-allocator.rs
new file mode 100644 (file)
index 0000000..e00c5ca
--- /dev/null
@@ -0,0 +1,7 @@
+// run-pass
+// compile-flags: -Z thinlto -C codegen-units=2
+
+#[global_allocator]
+static A: std::alloc::System = std::alloc::System;
+
+fn main() {}
diff --git a/src/test/ui/lto/thin-lto-inlines.rs b/src/test/ui/lto/thin-lto-inlines.rs
new file mode 100644 (file)
index 0000000..dca7918
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+
+// compile-flags: -Z thinlto -C codegen-units=8 -O
+// ignore-emscripten can't inspect instructions on emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+pub fn foo() -> u32 {
+    bar::bar()
+}
+
+mod bar {
+    pub fn bar() -> u32 {
+        3
+    }
+}
+
+fn main() {
+    println!("{} {}", foo(), bar::bar());
+
+    unsafe {
+        let foo = foo as usize as *const u8;
+        let bar = bar::bar as usize as *const u8;
+
+        assert_eq!(*foo, *bar);
+    }
+}
diff --git a/src/test/ui/lto/thin-lto-inlines2.rs b/src/test/ui/lto/thin-lto-inlines2.rs
new file mode 100644 (file)
index 0000000..1eb2965
--- /dev/null
@@ -0,0 +1,28 @@
+// run-pass
+
+// compile-flags: -C codegen-units=8 -O -C lto=thin
+// aux-build:thin-lto-inlines-aux.rs
+// no-prefer-dynamic
+// ignore-emscripten can't inspect instructions on emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+extern crate thin_lto_inlines_aux as bar;
+
+pub fn foo() -> u32 {
+    bar::bar()
+}
+
+fn main() {
+    println!("{} {}", foo(), bar::bar());
+
+    unsafe {
+        let foo = foo as usize as *const u8;
+        let bar = bar::bar as usize as *const u8;
+
+        assert_eq!(*foo, *bar);
+    }
+}
diff --git a/src/test/ui/lto/weak-works.rs b/src/test/ui/lto/weak-works.rs
new file mode 100644 (file)
index 0000000..163a387
--- /dev/null
@@ -0,0 +1,28 @@
+// run-pass
+
+// compile-flags: -C codegen-units=8 -Z thinlto
+// ignore-windows
+
+#![feature(linkage)]
+
+pub mod foo {
+    #[linkage = "weak"]
+    #[no_mangle]
+    pub extern "C" fn FOO() -> i32 {
+        0
+    }
+}
+
+mod bar {
+    extern "C" {
+        fn FOO() -> i32;
+    }
+
+    pub fn bar() -> i32 {
+        unsafe { FOO() }
+    }
+}
+
+fn main() {
+    bar::bar();
+}
diff --git a/src/test/ui/lub-glb-with-unbound-infer-var.rs b/src/test/ui/lub-glb-with-unbound-infer-var.rs
deleted file mode 100644 (file)
index c9e1170..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-// Test for a specific corner case: when we compute the LUB of two fn
-// types and their parameters have unbound variables. In that case, we
-// wind up relating those two variables. This was causing an ICE in an
-// in-progress PR.
-
-fn main() {
-    let a_f: fn(_) = |_| ();
-    let b_f: fn(_) = |_| ();
-    let c_f = match 22 {
-        0 => a_f,
-        _ => b_f,
-    };
-    c_f(4);
-}
diff --git a/src/test/ui/macros/auxiliary/issue-19163.rs b/src/test/ui/macros/auxiliary/issue-19163.rs
new file mode 100644 (file)
index 0000000..0c0d9e4
--- /dev/null
@@ -0,0 +1,6 @@
+#![crate_type = "lib"]
+
+#[macro_export]
+macro_rules! mywrite {
+    ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
+}
diff --git a/src/test/ui/macros/issue-16098.rs b/src/test/ui/macros/issue-16098.rs
new file mode 100644 (file)
index 0000000..00acc20
--- /dev/null
@@ -0,0 +1,16 @@
+macro_rules! prob1 {
+    (0) => {
+        0
+    };
+    ($n:expr) => {
+        if ($n % 3 == 0) || ($n % 5 == 0) {
+            $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding `prob1!`
+        } else {
+            prob1!($n - 1);
+        }
+    };
+}
+
+fn main() {
+    println!("Problem 1: {}", prob1!(1000));
+}
diff --git a/src/test/ui/macros/issue-16098.stderr b/src/test/ui/macros/issue-16098.stderr
new file mode 100644 (file)
index 0000000..6428021
--- /dev/null
@@ -0,0 +1,14 @@
+error: recursion limit reached while expanding `prob1!`
+  --> $DIR/issue-16098.rs:7:18
+   |
+LL |             $n + prob1!($n - 1);
+   |                  ^^^^^^^^^^^^^^
+...
+LL |     println!("Problem 1: {}", prob1!(1000));
+   |                               ------------ in this macro invocation
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`)
+   = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-19163.rs b/src/test/ui/macros/issue-19163.rs
new file mode 100644 (file)
index 0000000..d98c591
--- /dev/null
@@ -0,0 +1,11 @@
+// aux-build:issue-19163.rs
+
+#[macro_use] extern crate issue_19163;
+
+use std::io::Write;
+
+fn main() {
+    let mut v = vec![];
+    mywrite!(&v, "Hello world");
+    //~^ ERROR cannot borrow data in a `&` reference as mutable
+}
diff --git a/src/test/ui/macros/issue-19163.stderr b/src/test/ui/macros/issue-19163.stderr
new file mode 100644 (file)
index 0000000..ae1ae14
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/issue-19163.rs:9:5
+   |
+LL |     mywrite!(&v, "Hello world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = note: this error originates in the macro `mywrite` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/macros/issue-21356.rs b/src/test/ui/macros/issue-21356.rs
new file mode 100644 (file)
index 0000000..ae62392
--- /dev/null
@@ -0,0 +1,6 @@
+#![allow(unused_macros)]
+
+macro_rules! test { ($wrong:t_ty ..) => () }
+                  //~^ ERROR: invalid fragment specifier `t_ty`
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-21356.stderr b/src/test/ui/macros/issue-21356.stderr
new file mode 100644 (file)
index 0000000..17014c6
--- /dev/null
@@ -0,0 +1,10 @@
+error: invalid fragment specifier `t_ty`
+  --> $DIR/issue-21356.rs:3:22
+   |
+LL | macro_rules! test { ($wrong:t_ty ..) => () }
+   |                      ^^^^^^^^^^^
+   |
+   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-22463.rs b/src/test/ui/macros/issue-22463.rs
new file mode 100644 (file)
index 0000000..fdf5a2f
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+macro_rules! items {
+    () => {
+        type A = ();
+        fn a() {}
+    }
+}
+
+trait Foo {
+    type A;
+    fn a();
+}
+
+impl Foo for () {
+    items!();
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/macros/issue-29084.rs b/src/test/ui/macros/issue-29084.rs
new file mode 100644 (file)
index 0000000..d162526
--- /dev/null
@@ -0,0 +1,13 @@
+macro_rules! foo {
+    ($d:expr) => {{
+        fn bar(d: u8) { }
+        bar(&mut $d);
+        //~^ ERROR mismatched types
+        //~| expected `u8`, found `&mut u8`
+    }}
+}
+
+fn main() {
+    foo!(0u8);
+    //~^ in this expansion of foo!
+}
diff --git a/src/test/ui/macros/issue-29084.stderr b/src/test/ui/macros/issue-29084.stderr
new file mode 100644 (file)
index 0000000..a973e23
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-29084.rs:4:13
+   |
+LL |         bar(&mut $d);
+   |             ^^^^^^^ expected `u8`, found `&mut u8`
+...
+LL |     foo!(0u8);
+   |     --------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/macros/issue-34171.rs b/src/test/ui/macros/issue-34171.rs
new file mode 100644 (file)
index 0000000..157c58c
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+macro_rules! null { ($i:tt) => {} }
+macro_rules! apply_null {
+    ($i:item) => { null! { $i } }
+}
+
+fn main() {
+    apply_null!(#[cfg(all())] fn f() {});
+}
diff --git a/src/test/ui/macros/issue-37175.rs b/src/test/ui/macros/issue-37175.rs
new file mode 100644 (file)
index 0000000..9ec9d48
--- /dev/null
@@ -0,0 +1,5 @@
+// run-pass
+macro_rules! m { (<$t:ty>) => { stringify!($t) } }
+fn main() {
+    println!("{}", m!(<Vec<i32>>));
+}
diff --git a/src/test/ui/macros/issue-39388.rs b/src/test/ui/macros/issue-39388.rs
new file mode 100644 (file)
index 0000000..a8e31a6
--- /dev/null
@@ -0,0 +1,9 @@
+#![allow(unused_macros)]
+
+macro_rules! assign {
+    (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
+        $($a)* = $($b)*
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-39388.stderr b/src/test/ui/macros/issue-39388.stderr
new file mode 100644 (file)
index 0000000..62e7dff
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of: `*`, `+`, or `?`
+  --> $DIR/issue-39388.rs:4:22
+   |
+LL |     (($($a:tt)*) = ($($b:tt))*) => {
+   |                      ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-40770.rs b/src/test/ui/macros/issue-40770.rs
new file mode 100644 (file)
index 0000000..c9713c1
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+#![allow(unused_macros)]
+macro_rules! m {
+    ($e:expr) => {
+        macro_rules! n { () => { $e } }
+    }
+}
+
+fn main() {
+    m!(foo!());
+}
diff --git a/src/test/ui/macros/issue-57597.rs b/src/test/ui/macros/issue-57597.rs
new file mode 100644 (file)
index 0000000..ebeb3fe
--- /dev/null
@@ -0,0 +1,80 @@
+// Regression test for #57597.
+//
+// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
+
+// edition:2018
+
+macro_rules! foo1 {
+    ($($($i:ident)?)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo2 {
+    ($($($i:ident)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo3 {
+    ($($($i:ident)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo4 {
+    ($($($($i:ident)?)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo5 {
+    ($($($($i:ident)*)?)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo6 {
+    ($($($($i:ident)?)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo7 {
+    ($($($($i:ident)?)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo8 {
+    ($($($($i:ident)*)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo9 {
+    ($($($($i:ident)?)*)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo10 {
+    ($($($($i:ident)?)*)+) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo11 {
+    ($($($($i:ident)+)?)*) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo12 {
+    ($($($($i:ident)+)*)?) => {};
+    //~^ ERROR repetition matches empty token tree
+}
+
+fn main() {
+    foo1!();
+    foo2!();
+    foo3!();
+    foo4!();
+    foo5!();
+    foo6!();
+    foo7!();
+    foo8!();
+    foo9!();
+    foo10!();
+    foo11!();
+    foo12!();
+}
diff --git a/src/test/ui/macros/issue-57597.stderr b/src/test/ui/macros/issue-57597.stderr
new file mode 100644 (file)
index 0000000..0a02ac8
--- /dev/null
@@ -0,0 +1,74 @@
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:8:7
+   |
+LL |     ($($($i:ident)?)+) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:13:7
+   |
+LL |     ($($($i:ident)?)*) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:18:7
+   |
+LL |     ($($($i:ident)?)?) => {};
+   |       ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:23:7
+   |
+LL |     ($($($($i:ident)?)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:28:7
+   |
+LL |     ($($($($i:ident)*)?)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:33:7
+   |
+LL |     ($($($($i:ident)?)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:38:7
+   |
+LL |     ($($($($i:ident)?)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:43:7
+   |
+LL |     ($($($($i:ident)*)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:48:7
+   |
+LL |     ($($($($i:ident)?)*)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:53:7
+   |
+LL |     ($($($($i:ident)?)*)+) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:58:7
+   |
+LL |     ($($($($i:ident)+)?)*) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+  --> $DIR/issue-57597.rs:63:7
+   |
+LL |     ($($($($i:ident)+)*)?) => {};
+   |       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/macros/issue-6596-1.rs b/src/test/ui/macros/issue-6596-1.rs
new file mode 100644 (file)
index 0000000..25f1d65
--- /dev/null
@@ -0,0 +1,10 @@
+macro_rules! e {
+    ($inp:ident) => (
+        $nonexistent
+        //~^ ERROR expected expression, found `$`
+    );
+}
+
+fn main() {
+    e!(foo);
+}
diff --git a/src/test/ui/macros/issue-6596-1.stderr b/src/test/ui/macros/issue-6596-1.stderr
new file mode 100644 (file)
index 0000000..7ab3685
--- /dev/null
@@ -0,0 +1,13 @@
+error: expected expression, found `$`
+  --> $DIR/issue-6596-1.rs:3:9
+   |
+LL |         $nonexistent
+   |         ^^^^^^^^^^^^ expected expression
+...
+LL |     e!(foo);
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/issue-86865.rs b/src/test/ui/macros/issue-86865.rs
new file mode 100644 (file)
index 0000000..01e0a20
--- /dev/null
@@ -0,0 +1,11 @@
+use std::fmt::Write;
+
+fn main() {
+    println!(b"foo");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+    let mut s = String::new();
+    write!(s, b"foo{}", "bar");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+}
diff --git a/src/test/ui/macros/issue-86865.stderr b/src/test/ui/macros/issue-86865.stderr
new file mode 100644 (file)
index 0000000..eed7553
--- /dev/null
@@ -0,0 +1,18 @@
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:4:14
+   |
+LL |     println!(b"foo");
+   |              -^^^^^
+   |              |
+   |              help: consider removing the leading `b`
+
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:8:15
+   |
+LL |     write!(s, b"foo{}", "bar");
+   |               -^^^^^^^
+   |               |
+   |               help: consider removing the leading `b`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/trace_macros-format.rs b/src/test/ui/macros/trace_macros-format.rs
new file mode 100644 (file)
index 0000000..afca45c
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(trace_macros)]
+
+fn main() {
+    trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
+    trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
+
+
+    // should be fine:
+    macro_rules! expando {
+        ($x: ident) => { trace_macros!($x) }
+    }
+
+    expando!(true);
+}
diff --git a/src/test/ui/macros/trace_macros-format.stderr b/src/test/ui/macros/trace_macros-format.stderr
new file mode 100644 (file)
index 0000000..c320270
--- /dev/null
@@ -0,0 +1,38 @@
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:4:5
+   |
+LL |     trace_macros!();
+   |     ^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:5:5
+   |
+LL |     trace_macros!(1);
+   |     ^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:6:5
+   |
+LL |     trace_macros!(ident);
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:7:5
+   |
+LL |     trace_macros!(for);
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:8:5
+   |
+LL |     trace_macros!(true,);
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+  --> $DIR/trace_macros-format.rs:9:5
+   |
+LL |     trace_macros!(false 1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs
new file mode 100644 (file)
index 0000000..1e41312
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+
+#![feature(marker_trait_attr)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+#[marker]
+trait MyMarker {}
+
+impl<T> MyMarker for T {}
+impl<T> MyMarker for Vec<T> {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+    t
+}
+
+fn main() {
+    assert_eq!(1, foo(1));
+    assert_eq!(2.0, foo(2.0));
+    assert_eq!(vec![1], foo(vec![1]));
+}
diff --git a/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr
new file mode 100644 (file)
index 0000000..fca9866
--- /dev/null
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs b/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs
new file mode 100644 (file)
index 0000000..3833139
--- /dev/null
@@ -0,0 +1,26 @@
+// run-pass
+// Tests for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits with #[marker]. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`.
+
+#![feature(marker_trait_attr)]
+
+use std::fmt::{Debug, Display};
+
+#[marker] trait MyMarker {}
+
+impl<T: Debug> MyMarker for T {}
+impl<T: Display> MyMarker for T {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+    t
+}
+
+fn main() {
+    // Debug && Display:
+    assert_eq!(1, foo(1));
+    assert_eq!(2.0, foo(2.0));
+
+    // Debug && !Display:
+    assert_eq!(vec![1], foo(vec![1]));
+}
diff --git a/src/test/ui/match/issue-11940.rs b/src/test/ui/match/issue-11940.rs
new file mode 100644 (file)
index 0000000..6815c87
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+
+const TEST_STR: &'static str = "abcd";
+
+fn main() {
+    let s = "abcd";
+    match s {
+        TEST_STR => (),
+        _ => unreachable!()
+    }
+}
diff --git a/src/test/ui/match/issue-18060.rs b/src/test/ui/match/issue-18060.rs
new file mode 100644 (file)
index 0000000..b5f3d0f
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+// Regression test for #18060: match arms were matching in the wrong order.
+
+fn main() {
+    assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+    assert_eq!(2, match (1, 3) {                  (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+    assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+}
diff --git a/src/test/ui/match/issue-26251.rs b/src/test/ui/match/issue-26251.rs
new file mode 100644 (file)
index 0000000..a3e26a4
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(overlapping_range_endpoints)]
+
+fn main() {
+    let x = 'a';
+
+    let y = match x {
+        'a'..='b' if false => "one",
+        'a' => "two",
+        'a'..='b' => "three",
+        _ => panic!("what?"),
+    };
+
+    assert_eq!(y, "two");
+}
diff --git a/src/test/ui/match/issue-26996.rs b/src/test/ui/match/issue-26996.rs
new file mode 100644 (file)
index 0000000..84037b7
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+
+// This test is bogus (i.e., should be check-fail) during the period
+// where #54986 is implemented and #54987 is *not* implemented. For
+// now: just ignore it
+//
+// ignore-test
+
+// This test is checking that the write to `c.0` (which has been moved out of)
+// won't overwrite the state in `c2`.
+//
+// That's a fine thing to test when this code is accepted by the
+// compiler, and this code is being transcribed accordingly into
+// the ui test issue-21232-partial-init-and-use.rs
+
+fn main() {
+    let mut c = (1, "".to_owned());
+    match c {
+        c2 => {
+            c.0 = 2;
+            assert_eq!(c2.0, 1);
+        }
+    }
+}
diff --git a/src/test/ui/match/issue-42679.rs b/src/test/ui/match/issue-42679.rs
new file mode 100644 (file)
index 0000000..596309f
--- /dev/null
@@ -0,0 +1,22 @@
+// run-pass
+#![feature(box_syntax)]
+#![feature(box_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum Test {
+    Foo(usize),
+    Bar(isize),
+}
+
+fn main() {
+    let a = box Test::Foo(10);
+    let b = box Test::Bar(-20);
+    match (a, b) {
+        (_, box Test::Foo(_)) => unreachable!(),
+        (box Test::Foo(x), b) => {
+            assert_eq!(x, 10);
+            assert_eq!(b, box Test::Bar(-20));
+        },
+        _ => unreachable!(),
+    }
+}
diff --git a/src/test/ui/mir/issue-74739.rs b/src/test/ui/mir/issue-74739.rs
new file mode 100644 (file)
index 0000000..0362235
--- /dev/null
@@ -0,0 +1,14 @@
+// compile-flags: -O
+// run-pass
+
+struct Foo {
+    x: i32,
+}
+
+pub fn main() {
+    let mut foo = Foo { x: 42 };
+    let x = &mut foo.x;
+    *x = 13;
+    let y = foo;
+    assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
+}
diff --git a/src/test/ui/mut-vstore-expr.rs b/src/test/ui/mut-vstore-expr.rs
deleted file mode 100644 (file)
index 75b309a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-pub fn main() {
-    let _x: &mut [isize] = &mut [ 1, 2, 3 ];
-}
diff --git a/src/test/ui/negative.rs b/src/test/ui/negative.rs
deleted file mode 100644 (file)
index 9601e91..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-pub fn main() {
-    match -5 {
-      -5 => {}
-      _ => { panic!() }
-    }
-}
diff --git a/src/test/ui/nested_item_main.rs b/src/test/ui/nested_item_main.rs
deleted file mode 100644 (file)
index 2fe00ae..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// run-pass
-// aux-build:nested_item.rs
-
-
-extern crate nested_item;
-
-pub fn main() {
-    assert_eq!(2, nested_item::foo::<()>());
-    assert_eq!(2, nested_item::foo::<isize>());
-}
diff --git a/src/test/ui/never_type/diverging-tuple-parts-39485.rs b/src/test/ui/never_type/diverging-tuple-parts-39485.rs
new file mode 100644 (file)
index 0000000..0cde611
--- /dev/null
@@ -0,0 +1,15 @@
+// After #39485, this test used to pass, but that change was reverted
+// due to numerous inference failures like #39808, so it now fails
+// again. #39485 made it so that diverging types never propagate
+// upward; but we now do propagate such types upward in many more
+// cases.
+
+fn g() {
+    &panic!() //~ ERROR mismatched types
+}
+
+fn f() -> isize {
+    (return 1, return 2) //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/never_type/diverging-tuple-parts-39485.stderr b/src/test/ui/never_type/diverging-tuple-parts-39485.stderr
new file mode 100644 (file)
index 0000000..32967b3
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0308]: mismatched types
+  --> $DIR/diverging-tuple-parts-39485.rs:8:5
+   |
+LL |     &panic!()
+   |     ^^^^^^^^^ expected `()`, found reference
+   |
+   = note: expected unit type `()`
+              found reference `&_`
+help: try adding a return type
+   |
+LL | fn g() -> &_ {
+   |        +++++
+help: consider removing the borrow
+   |
+LL -     &panic!()
+LL +     panic!()
+   | 
+
+error[E0308]: mismatched types
+  --> $DIR/diverging-tuple-parts-39485.rs:12:5
+   |
+LL | fn f() -> isize {
+   |           ----- expected `isize` because of return type
+LL |     (return 1, return 2)
+   |     ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
+   |
+   = note: expected type `isize`
+             found tuple `(!, !)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/new-box.rs b/src/test/ui/new-box.rs
deleted file mode 100644 (file)
index 96a3b19..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-
-fn f(x: Box<isize>) {
-    let y: &isize = &*x;
-    println!("{}", *x);
-    println!("{}", *y);
-}
-
-trait Trait {
-    fn printme(&self);
-}
-
-struct Struct;
-
-impl Trait for Struct {
-    fn printme(&self) {
-        println!("hello world!");
-    }
-}
-
-fn g(x: Box<dyn Trait>) {
-    x.printme();
-    let y: &dyn Trait = &*x;
-    y.printme();
-}
-
-fn main() {
-    f(Box::new(1234));
-    g(Box::new(Struct) as Box<dyn Trait>);
-}
diff --git a/src/test/ui/nil-decl-in-foreign.rs b/src/test/ui/nil-decl-in-foreign.rs
deleted file mode 100644 (file)
index f3be948..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-
-#![allow(improper_ctypes)]
-#![allow(dead_code)]
-// Issue #901
-// pretty-expanded FIXME #23616
-
-mod libc {
-    extern "C" {
-        pub fn printf(x: ());
-    }
-}
-
-pub fn main() {}
diff --git a/src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs b/src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs
new file mode 100644 (file)
index 0000000..a4d0a84
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+
+pub fn main() {
+    let a = 1;
+    let a_neg: i8 = -a;
+    println!("{}", a_neg);
+
+    let b = 1;
+    let b_neg: i16 = -b;
+    println!("{}", b_neg);
+
+    let c = 1;
+    let c_neg: i32 = -c;
+    println!("{}", c_neg);
+
+    let d = 1;
+    let d_neg: i64 = -d;
+    println!("{}", d_neg);
+
+    let e = 1;
+    let e_neg: isize = -e;
+    println!("{}", e_neg);
+}
diff --git a/src/test/ui/object-does-not-impl-trait.rs b/src/test/ui/object-does-not-impl-trait.rs
deleted file mode 100644 (file)
index b3b6798..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// Test that an object type `Box<Foo>` is not considered to implement the
-// trait `Foo`. Issue #5087.
-
-trait Foo {}
-fn take_foo<F:Foo>(f: F) {}
-fn take_object(f: Box<dyn Foo>) { take_foo(f); }
-//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied
-fn main() {}
diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr
deleted file mode 100644 (file)
index f1dd508..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
-  --> $DIR/object-does-not-impl-trait.rs:6:44
-   |
-LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
-   |                                   -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
-   |                                   |
-   |                                   required by a bound introduced by this call
-   |
-note: required by a bound in `take_foo`
-  --> $DIR/object-does-not-impl-trait.rs:5:15
-   |
-LL | fn take_foo<F:Foo>(f: F) {}
-   |               ^^^ required by this bound in `take_foo`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
deleted file mode 100644 (file)
index 1e41312..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-
-#![feature(marker_trait_attr)]
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-#[marker]
-trait MyMarker {}
-
-impl<T> MyMarker for T {}
-impl<T> MyMarker for Vec<T> {}
-
-fn foo<T: MyMarker>(t: T) -> T {
-    t
-}
-
-fn main() {
-    assert_eq!(1, foo(1));
-    assert_eq!(2.0, foo(2.0));
-    assert_eq!(vec![1], foo(vec![1]));
-}
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr
deleted file mode 100644 (file)
index fca9866..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/overlap-permitted-for-annotated-marker-traits.rs b/src/test/ui/overlap-permitted-for-annotated-marker-traits.rs
deleted file mode 100644 (file)
index 3833139..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// run-pass
-// Tests for RFC 1268: we allow overlapping impls of marker traits,
-// that is, traits with #[marker]. In this case, a type `T` is
-// `MyMarker` if it is either `Debug` or `Display`.
-
-#![feature(marker_trait_attr)]
-
-use std::fmt::{Debug, Display};
-
-#[marker] trait MyMarker {}
-
-impl<T: Debug> MyMarker for T {}
-impl<T: Display> MyMarker for T {}
-
-fn foo<T: MyMarker>(t: T) -> T {
-    t
-}
-
-fn main() {
-    // Debug && Display:
-    assert_eq!(1, foo(1));
-    assert_eq!(2.0, foo(2.0));
-
-    // Debug && !Display:
-    assert_eq!(vec![1], foo(vec![1]));
-}
diff --git a/src/test/ui/packed/issue-46152.rs b/src/test/ui/packed/issue-46152.rs
new file mode 100644 (file)
index 0000000..fb1c9fb
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![feature(unsize, coerce_unsized)]
+
+#[repr(packed)]
+struct UnalignedPtr<'a, T: ?Sized>
+    where T: 'a,
+{
+    data: &'a T,
+}
+
+fn main() {
+
+    impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
+        where
+        T: std::marker::Unsize<U> + ?Sized,
+        U: ?Sized,
+    { }
+
+    let arr = [1, 2, 3];
+    let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
+    let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
+}
diff --git a/src/test/ui/parser/bastion-of-the-turbofish.rs b/src/test/ui/parser/bastion-of-the-turbofish.rs
new file mode 100644 (file)
index 0000000..e128570
--- /dev/null
@@ -0,0 +1,43 @@
+// check-pass
+
+// Bastion of the Turbofish
+// ------------------------
+// Beware travellers, lest you venture into waters callous and unforgiving,
+// where hope must be abandoned, ere it is cruelly torn from you. For here
+// stands the bastion of the Turbofish: an impenetrable fortress holding
+// unshaking against those who would dare suggest the supererogation of the
+// Turbofish.
+//
+// Once I was young and foolish and had the impudence to imagine that I could
+// shake free from the coils by which that creature had us tightly bound. I
+// dared to suggest that there was a better way: a brighter future, in which
+// Rustaceans both new and old could be rid of that vile beast. But alas! In
+// my foolhardiness my ignorance was unveiled and my dreams were dashed
+// unforgivingly against the rock of syntactic ambiguity.
+//
+// This humble program, small and insignificant though it might seem,
+// demonstrates that to which we had previously cast a blind eye: an ambiguity
+// in permitting generic arguments to be provided without the consent of the
+// Great Turbofish. Should you be so naïve as to try to revolt against its
+// mighty clutches, here shall its wrath be indomitably displayed. This
+// program must pass for all eternity: forever watched by the guardian angel
+// which gave this beast its name, and stands fundamentally at odds with the
+// impetuous rebellion against the Turbofish.
+//
+// My heart aches in sorrow, for I know I am defeated. Let this be a warning
+// to all those who come after: for they too must overcome the impassible
+// hurdle of defeating the great beast, championed by a resolute winged
+// guardian.
+//
+// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
+// Guardian Angel of these Hallowed Grounds. <3
+
+// See https://github.com/rust-lang/rust/pull/53562
+// and https://github.com/rust-lang/rfcs/pull/2527
+// and https://twitter.com/garblefart/status/1393236602856611843
+// for context.
+
+fn main() {
+    let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
+    let _: (bool, bool) = (the<guardian, stands>(resolute));
+}
diff --git a/src/test/ui/parser/issue-13483.rs b/src/test/ui/parser/issue-13483.rs
new file mode 100644 (file)
index 0000000..a2fd926
--- /dev/null
@@ -0,0 +1,17 @@
+fn main() {
+    if true {
+    } else if { //~ ERROR missing condition
+    //~^ ERROR mismatched types
+    } else {
+    }
+}
+
+fn foo() {
+    if true {
+    } else if { //~ ERROR missing condition
+    //~^ ERROR mismatched types
+    }
+    bar();
+}
+
+fn bar() {}
diff --git a/src/test/ui/parser/issue-13483.stderr b/src/test/ui/parser/issue-13483.stderr
new file mode 100644 (file)
index 0000000..5fd05b1
--- /dev/null
@@ -0,0 +1,33 @@
+error: missing condition for `if` expression
+  --> $DIR/issue-13483.rs:3:14
+   |
+LL |     } else if {
+   |              ^ expected if condition here
+
+error: missing condition for `if` expression
+  --> $DIR/issue-13483.rs:11:14
+   |
+LL |     } else if {
+   |              ^ expected if condition here
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13483.rs:3:15
+   |
+LL |       } else if {
+   |  _______________^
+LL | |
+LL | |     } else {
+   | |_____^ expected `bool`, found `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13483.rs:11:15
+   |
+LL |       } else if {
+   |  _______________^
+LL | |
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-20616-4.rs b/src/test/ui/parser/issue-20616-4.rs
new file mode 100644 (file)
index 0000000..a71f47c
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+type Type_4<T> = Type_1_<'static,, T>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-4.stderr b/src/test/ui/parser/issue-20616-4.stderr
new file mode 100644 (file)
index 0000000..2b3b75f
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-4.rs:16:34
+   |
+LL | type Type_4<T> = Type_1_<'static,, T>;
+   |                                  ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20616-5.rs b/src/test/ui/parser/issue-20616-5.rs
new file mode 100644 (file)
index 0000000..b96d09d
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+type Type_5<'a> = Type_1_<'a, (),,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-5.stderr b/src/test/ui/parser/issue-20616-5.stderr
new file mode 100644 (file)
index 0000000..1ec1dbd
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-5.rs:22:34
+   |
+LL | type Type_5<'a> = Type_1_<'a, (),,>;
+   |                                  ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20616-6.rs b/src/test/ui/parser/issue-20616-6.rs
new file mode 100644 (file)
index 0000000..a2c45ec
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+type Type_6 = Type_5_<'a,,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-6.stderr b/src/test/ui/parser/issue-20616-6.stderr
new file mode 100644 (file)
index 0000000..7401abd
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-6.rs:25:26
+   |
+LL | type Type_6 = Type_5_<'a,,>;
+   |                          ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-20616-7.rs b/src/test/ui/parser/issue-20616-7.rs
new file mode 100644 (file)
index 0000000..67209c0
--- /dev/null
@@ -0,0 +1,35 @@
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+type Type_7 = Box<(),,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
diff --git a/src/test/ui/parser/issue-20616-7.stderr b/src/test/ui/parser/issue-20616-7.stderr
new file mode 100644 (file)
index 0000000..e2c3efe
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+  --> $DIR/issue-20616-7.rs:28:22
+   |
+LL | type Type_7 = Box<(),,>;
+   |                      ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-21475.rs b/src/test/ui/parser/issue-21475.rs
new file mode 100644 (file)
index 0000000..b028fca
--- /dev/null
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(unused_imports, overlapping_range_endpoints)]
+// pretty-expanded FIXME #23616
+
+use m::{START, END};
+
+fn main() {
+    match 42 {
+        m::START..=m::END => {},
+        0..=m::END => {},
+        m::START..=59 => {},
+        _  => {},
+    }
+}
+
+mod m {
+  pub const START: u32 = 4;
+  pub const END:   u32 = 14;
+}
diff --git a/src/test/ui/parser/issue-31804.rs b/src/test/ui/parser/issue-31804.rs
new file mode 100644 (file)
index 0000000..d056b77
--- /dev/null
@@ -0,0 +1,6 @@
+// Test that error recovery in the parser to an EOF does not give an infinite
+// spew of errors.
+
+fn main() {
+    let
+} //~ ERROR expected pattern, found `}`
diff --git a/src/test/ui/parser/issue-31804.stderr b/src/test/ui/parser/issue-31804.stderr
new file mode 100644 (file)
index 0000000..76e68b0
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected pattern, found `}`
+  --> $DIR/issue-31804.rs:6:1
+   |
+LL | }
+   | ^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-34255-1.rs b/src/test/ui/parser/issue-34255-1.rs
new file mode 100644 (file)
index 0000000..c70cd8b
--- /dev/null
@@ -0,0 +1,10 @@
+enum Test {
+    Drill {
+        field: i32,
+    }
+}
+
+fn main() {
+    Test::Drill(field: 42);
+    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
+}
diff --git a/src/test/ui/parser/issue-34255-1.stderr b/src/test/ui/parser/issue-34255-1.stderr
new file mode 100644 (file)
index 0000000..fbff75e
--- /dev/null
@@ -0,0 +1,18 @@
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-34255-1.rs:8:5
+   |
+LL |     Test::Drill(field: 42);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if `Test::Drill` is a struct, use braces as delimiters
+   |
+LL |     Test::Drill { field: 42 };
+   |                 ~           ~
+help: if `Test::Drill` is a function, use the arguments directly
+   |
+LL -     Test::Drill(field: 42);
+LL +     Test::Drill(42);
+   | 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issue-49040.rs b/src/test/ui/parser/issue-49040.rs
new file mode 100644 (file)
index 0000000..b7a541d
--- /dev/null
@@ -0,0 +1,3 @@
+#![allow(unused_variables)]; //~ ERROR expected item, found `;`
+//~^ ERROR `main` function
+fn foo() {}
diff --git a/src/test/ui/parser/issue-49040.stderr b/src/test/ui/parser/issue-49040.stderr
new file mode 100644 (file)
index 0000000..56befe3
--- /dev/null
@@ -0,0 +1,15 @@
+error: expected item, found `;`
+  --> $DIR/issue-49040.rs:1:28
+   |
+LL | #![allow(unused_variables)];
+   |                            ^ help: remove this semicolon
+
+error[E0601]: `main` function not found in crate `issue_49040`
+  --> $DIR/issue-49040.rs:1:1
+   |
+LL | #![allow(unused_variables)];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/issue-56031.rs b/src/test/ui/parser/issue-56031.rs
new file mode 100644 (file)
index 0000000..b68f568
--- /dev/null
@@ -0,0 +1,6 @@
+struct T;
+
+impl for T {}
+//~^ ERROR missing trait in a trait impl
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-56031.stderr b/src/test/ui/parser/issue-56031.stderr
new file mode 100644 (file)
index 0000000..7ee5bc6
--- /dev/null
@@ -0,0 +1,18 @@
+error: missing trait in a trait impl
+  --> $DIR/issue-56031.rs:3:5
+   |
+LL | impl for T {}
+   |     ^
+   |
+help: add a trait here
+   |
+LL | impl Trait for T {}
+   |      +++++
+help: for an inherent impl, drop this `for`
+   |
+LL - impl for T {}
+LL + impl T {}
+   | 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/issue-11577.rs b/src/test/ui/pattern/issue-11577.rs
new file mode 100644 (file)
index 0000000..70177c5
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+// Destructuring struct variants would ICE where regular structs wouldn't
+
+enum Foo {
+    VBar { num: isize }
+}
+
+struct SBar { num: isize }
+
+pub fn main() {
+    let vbar = Foo::VBar { num: 1 };
+    let Foo::VBar { num } = vbar;
+    assert_eq!(num, 1);
+
+    let sbar = SBar { num: 2 };
+    let SBar { num } = sbar;
+    assert_eq!(num, 2);
+}
diff --git a/src/test/ui/pattern/issue-15080.rs b/src/test/ui/pattern/issue-15080.rs
new file mode 100644 (file)
index 0000000..4dd6981
--- /dev/null
@@ -0,0 +1,22 @@
+// run-pass
+
+fn main() {
+    let mut x: &[_] = &[1, 2, 3, 4];
+
+    let mut result = vec![];
+    loop {
+        x = match *x {
+            [1, n, 3, ref rest @ ..] => {
+                result.push(n);
+                rest
+            }
+            [n, ref rest @ ..] => {
+                result.push(n);
+                rest
+            }
+            [] =>
+                break
+        }
+    }
+    assert_eq!(result, [2, 4]);
+}
diff --git a/src/test/ui/pattern/issue-72574-2.rs b/src/test/ui/pattern/issue-72574-2.rs
new file mode 100644 (file)
index 0000000..0ad2db8
--- /dev/null
@@ -0,0 +1,12 @@
+struct Binder(i32, i32, i32);
+
+fn main() {
+    let x = Binder(1, 2, 3);
+    match x {
+        Binder(_a, _x @ ..) => {}
+        _ => {}
+    }
+}
+//~^^^^ ERROR `_x @` is not allowed in a tuple struct
+//~| ERROR: `..` patterns are not allowed here
+//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
diff --git a/src/test/ui/pattern/issue-72574-2.stderr b/src/test/ui/pattern/issue-72574-2.stderr
new file mode 100644 (file)
index 0000000..05650f0
--- /dev/null
@@ -0,0 +1,37 @@
+error: `_x @` is not allowed in a tuple struct
+  --> $DIR/issue-72574-2.rs:6:20
+   |
+LL |         Binder(_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 |         Binder(_a, ..) => {}
+   |                    ~~
+
+error: `..` patterns are not allowed here
+  --> $DIR/issue-72574-2.rs:6:25
+   |
+LL |         Binder(_a, _x @ ..) => {}
+   |                         ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/issue-72574-2.rs:6:16
+   |
+LL | struct Binder(i32, i32, i32);
+   |               ---  ---  --- tuple struct has 3 fields
+...
+LL |         Binder(_a, _x @ ..) => {}
+   |                ^^  ^^^^^^^ expected 3 fields, found 2
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         Binder(_a, _x @ .., _) => {}
+   |                           +++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/issue-8351-1.rs b/src/test/ui/pattern/issue-8351-1.rs
new file mode 100644 (file)
index 0000000..139f027
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+
+enum E {
+    Foo{f: isize},
+    Bar,
+}
+
+pub fn main() {
+    let e = E::Foo{f: 0};
+    match e {
+        E::Foo{f: 1} => panic!(),
+        E::Foo{..} => (),
+        _ => panic!(),
+    }
+}
diff --git a/src/test/ui/pattern/issue-8351-2.rs b/src/test/ui/pattern/issue-8351-2.rs
new file mode 100644 (file)
index 0000000..bc66cbb
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![allow(dead_code)]
+
+enum E {
+    Foo{f: isize, b: bool},
+    Bar,
+}
+
+pub fn main() {
+    let e = E::Foo{f: 0, b: false};
+    match e {
+        E::Foo{f: 1, b: true} => panic!(),
+        E::Foo{b: false, f: 0} => (),
+        _ => panic!(),
+    }
+}
diff --git a/src/test/ui/proc-macro/auxiliary/expand-expr.rs b/src/test/ui/proc-macro/auxiliary/expand-expr.rs
new file mode 100644 (file)
index 0000000..2bc34f3
--- /dev/null
@@ -0,0 +1,80 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(warnings)]
+#![feature(proc_macro_expand, proc_macro_span)]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+use std::str::FromStr;
+
+#[proc_macro]
+pub fn expand_expr_is(input: TokenStream) -> TokenStream {
+    let mut iter = input.into_iter();
+    let mut expected_tts = Vec::new();
+    loop {
+        match iter.next() {
+            Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break,
+            Some(tt) => expected_tts.push(tt),
+            None => panic!("expected comma"),
+        }
+    }
+
+    let expected = expected_tts.into_iter().collect::<TokenStream>();
+    let expanded = iter.collect::<TokenStream>().expand_expr().expect("expand_expr failed");
+    assert!(
+        expected.to_string() == expanded.to_string(),
+        "assert failed\nexpected: `{}`\nexpanded: `{}`",
+        expected.to_string(),
+        expanded.to_string()
+    );
+
+    TokenStream::new()
+}
+
+#[proc_macro]
+pub fn expand_expr_fail(input: TokenStream) -> TokenStream {
+    match input.expand_expr() {
+        Ok(ts) => panic!("expand_expr unexpectedly succeeded: `{}`", ts),
+        Err(_) => TokenStream::new(),
+    }
+}
+
+#[proc_macro]
+pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream {
+    // Check that the passed in `file!()` invocation and a parsed `file!`
+    // invocation expand to the same literal.
+    let input_t = ts.expand_expr().expect("expand_expr failed on macro input").to_string();
+    let parse_t = TokenStream::from_str("file!{}")
+    .unwrap()
+        .expand_expr()
+        .expect("expand_expr failed on internal macro")
+        .to_string();
+    assert_eq!(input_t, parse_t);
+
+    // Check that the literal matches `Span::call_site().source_file().path()`
+    let expect_t =
+        Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string();
+    assert_eq!(input_t, expect_t);
+
+    TokenStream::new()
+}
+
+#[proc_macro]
+pub fn recursive_expand(_: TokenStream) -> TokenStream {
+    // Recursively call until we hit the recursion limit and get an error.
+    //
+    // NOTE: This doesn't panic if expansion fails because that'll cause a very
+    // large number of errors to fill the output.
+    TokenStream::from_str("recursive_expand!{}")
+        .unwrap()
+        .expand_expr()
+        .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect())
+}
+
+#[proc_macro]
+pub fn echo_pm(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/ui/proc-macro/auxiliary/included-file.txt b/src/test/ui/proc-macro/auxiliary/included-file.txt
new file mode 100644 (file)
index 0000000..b472004
--- /dev/null
@@ -0,0 +1 @@
+Included file contents
diff --git a/src/test/ui/proc-macro/expand-expr.rs b/src/test/ui/proc-macro/expand-expr.rs
new file mode 100644 (file)
index 0000000..d1146d9
--- /dev/null
@@ -0,0 +1,121 @@
+// aux-build:expand-expr.rs
+
+extern crate expand_expr;
+
+use expand_expr::{
+    check_expand_expr_file, echo_pm, expand_expr_fail, expand_expr_is, recursive_expand,
+};
+
+// Check builtin macros can be expanded.
+
+expand_expr_is!(11u32, line!());
+expand_expr_is!(24u32, column!());
+
+expand_expr_is!("Hello, World!", concat!("Hello, ", "World", "!"));
+expand_expr_is!("int10floats5.3booltrue", concat!("int", 10, "floats", 5.3, "bool", true));
+expand_expr_is!("Hello", concat!(r##"Hello"##));
+
+expand_expr_is!("Included file contents\n", include_str!("auxiliary/included-file.txt"));
+expand_expr_is!(b"Included file contents\n", include_bytes!("auxiliary/included-file.txt"));
+
+expand_expr_is!(
+    "contents: Included file contents\n",
+    concat!("contents: ", include_str!("auxiliary/included-file.txt"))
+);
+
+// Correct value is checked for multiple sources.
+check_expand_expr_file!(file!());
+
+expand_expr_is!("hello", stringify!(hello));
+expand_expr_is!("10 + 20", stringify!(10 + 20));
+
+macro_rules! echo_tts {
+    ($($t:tt)*) => { $($t)* };  //~ ERROR: expected expression, found `$`
+}
+
+macro_rules! echo_lit {
+    ($l:literal) => {
+        $l
+    };
+}
+
+macro_rules! echo_expr {
+    ($e:expr) => {
+        $e
+    };
+}
+
+macro_rules! simple_lit {
+    ($l:literal) => {
+        expand_expr_is!($l, $l);
+        expand_expr_is!($l, echo_lit!($l));
+        expand_expr_is!($l, echo_expr!($l));
+        expand_expr_is!($l, echo_tts!($l));
+        expand_expr_is!($l, echo_pm!($l));
+        const _: () = {
+            macro_rules! mac {
+                () => {
+                    $l
+                };
+            }
+            expand_expr_is!($l, mac!());
+            expand_expr_is!($l, echo_expr!(mac!()));
+            expand_expr_is!($l, echo_tts!(mac!()));
+            expand_expr_is!($l, echo_pm!(mac!()));
+        };
+    };
+}
+
+simple_lit!("Hello, World");
+simple_lit!('c');
+simple_lit!(b'c');
+simple_lit!(10);
+simple_lit!(10.0);
+simple_lit!(10.0f64);
+simple_lit!(-3.14159);
+simple_lit!(-3.5e10);
+simple_lit!(0xFEED);
+simple_lit!(-0xFEED);
+simple_lit!(0b0100);
+simple_lit!(-0b0100);
+simple_lit!("string");
+simple_lit!(r##"raw string"##);
+simple_lit!(b"byte string");
+simple_lit!(br##"raw byte string"##);
+simple_lit!(true);
+simple_lit!(false);
+
+// Ensure char escapes aren't normalized by expansion
+simple_lit!("\u{0}");
+simple_lit!("\0");
+simple_lit!("\x00");
+simple_lit!('\u{0}');
+simple_lit!('\0');
+simple_lit!('\x00');
+simple_lit!(b"\x00");
+simple_lit!(b"\0");
+simple_lit!(b'\x00');
+simple_lit!(b'\0');
+
+// Extra tokens after the string literal aren't ignored
+expand_expr_fail!("string"; hello); //~ ERROR: expected one of `.`, `?`, or an operator, found `;`
+
+// Invalid expressions produce errors in addition to returning `Err(())`.
+expand_expr_fail!($); //~ ERROR: expected expression, found `$`
+expand_expr_fail!(echo_tts!($));
+expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$`
+
+// We get errors reported and recover during macro expansion if the macro
+// doesn't produce a valid expression.
+expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following
+expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following
+
+// For now, fail if a non-literal expression is expanded.
+expand_expr_fail!(arbitrary_expression() + "etc");
+expand_expr_fail!(echo_tts!(arbitrary_expression() + "etc"));
+expand_expr_fail!(echo_expr!(arbitrary_expression() + "etc"));
+expand_expr_fail!(echo_pm!(arbitrary_expression() + "etc"));
+
+const _: u32 = recursive_expand!(); //~ ERROR: recursion limit reached while expanding `recursive_expand!`
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/expand-expr.stderr b/src/test/ui/proc-macro/expand-expr.stderr
new file mode 100644 (file)
index 0000000..8dc2d0c
--- /dev/null
@@ -0,0 +1,55 @@
+error: expected one of `.`, `?`, or an operator, found `;`
+  --> $DIR/expand-expr.rs:101:27
+   |
+LL | expand_expr_fail!("string"; hello);
+   |                           ^ expected one of `.`, `?`, or an operator
+
+error: expected expression, found `$`
+  --> $DIR/expand-expr.rs:104:19
+   |
+LL | expand_expr_fail!($);
+   |                   ^ expected expression
+
+error: expected expression, found `$`
+  --> $DIR/expand-expr.rs:33:23
+   |
+LL |     ($($t:tt)*) => { $($t)* };
+   |                       ^^^^ expected expression
+
+error: expected expression, found `$`
+  --> $DIR/expand-expr.rs:106:28
+   |
+LL | expand_expr_fail!(echo_pm!($));
+   |                            ^ expected expression
+
+error: macro expansion ignores token `hello` and any following
+  --> $DIR/expand-expr.rs:110:47
+   |
+LL | expand_expr_is!("string", echo_tts!("string"; hello));
+   |                           --------------------^^^^^-- help: you might be missing a semicolon here: `;`
+   |                           |
+   |                           caused by the macro expansion here
+   |
+   = note: the usage of `echo_tts!` is likely invalid in expression context
+
+error: macro expansion ignores token `;` and any following
+  --> $DIR/expand-expr.rs:111:44
+   |
+LL | expand_expr_is!("string", echo_pm!("string"; hello));
+   |                           -----------------^-------- help: you might be missing a semicolon here: `;`
+   |                           |
+   |                           caused by the macro expansion here
+   |
+   = note: the usage of `echo_pm!` is likely invalid in expression context
+
+error: recursion limit reached while expanding `recursive_expand!`
+  --> $DIR/expand-expr.rs:119:16
+   |
+LL | const _: u32 = recursive_expand!();
+   |                ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`expand_expr`)
+   = note: this error originates in the macro `recursive_expand` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
index ada125a215a5d6cbaeb58702ecacdbd28a446fdf..69bfb4f3cbfbc5b4b77743a81c49f30897a8fd46 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 
-#![allow(dead_code)]
+#![allow(dead_code, unused_macros)]
 // aux-build:issue-39889.rs
 
 extern crate issue_39889;
diff --git a/src/test/ui/process/issue-14456.rs b/src/test/ui/process/issue-14456.rs
new file mode 100644 (file)
index 0000000..52a56eb
--- /dev/null
@@ -0,0 +1,37 @@
+// run-pass
+#![allow(unused_mut)]
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::env;
+use std::io::prelude::*;
+use std::io;
+use std::process::{Command, Stdio};
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() > 1 && args[1] == "child" {
+        return child()
+    }
+
+    test();
+}
+
+fn child() {
+    writeln!(&mut io::stdout(), "foo").unwrap();
+    writeln!(&mut io::stderr(), "bar").unwrap();
+    let mut stdin = io::stdin();
+    let mut s = String::new();
+    stdin.lock().read_line(&mut s).unwrap();
+    assert_eq!(s.len(), 0);
+}
+
+fn test() {
+    let args: Vec<String> = env::args().collect();
+    let mut p = Command::new(&args[0]).arg("child")
+                                     .stdin(Stdio::piped())
+                                     .stdout(Stdio::piped())
+                                     .stderr(Stdio::piped())
+                                     .spawn().unwrap();
+    assert!(p.wait().unwrap().success());
+}
diff --git a/src/test/ui/process/issue-16272.rs b/src/test/ui/process/issue-16272.rs
new file mode 100644 (file)
index 0000000..5cf3fd9
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::process::Command;
+use std::env;
+
+fn main() {
+    let len = env::args().len();
+
+    if len == 1 {
+        test();
+    } else {
+        assert_eq!(len, 3);
+    }
+}
+
+fn test() {
+    let status = Command::new(&env::current_exe().unwrap())
+                         .arg("foo").arg("")
+                         .status().unwrap();
+    assert!(status.success());
+}
diff --git a/src/test/ui/process/issue-20091.rs b/src/test/ui/process/issue-20091.rs
new file mode 100644 (file)
index 0000000..86cc79d
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+#![allow(stable_features)]
+
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+#![feature(os)]
+
+#[cfg(unix)]
+fn main() {
+    use std::process::Command;
+    use std::env;
+    use std::os::unix::prelude::*;
+    use std::ffi::OsStr;
+
+    if env::args().len() == 1 {
+        assert!(Command::new(&env::current_exe().unwrap())
+                        .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
+                        .status().unwrap().success())
+    }
+}
+
+#[cfg(windows)]
+fn main() {}
index ad749371beac041c4e56b691f5973ae772c18d3f..1ccf6bb051c20593c0e4d6f90f04669fbe8673e3 100644 (file)
 
 use libc::c_int;
 
-#[cfg(not(target_os = "linux"))]
-fn getpid() -> u32 {
-    process::id()
-}
-
-/// We need to directly use the getpid syscall instead of using `process::id()`
-/// because the libc wrapper might return incorrect values after a process was
-/// forked.
-#[cfg(target_os = "linux")]
-fn getpid() -> u32 {
-    unsafe {
-        libc::syscall(libc::SYS_getpid) as _
-    }
-}
-
 /// This stunt allocator allows us to spot heap allocations in the child.
 struct PidChecking<A> {
     parent: A,
@@ -59,7 +44,7 @@ fn engage(&self) {
     fn check(&self) {
         let require_pid = self.require_pid.load(Ordering::Acquire);
         if require_pid != 0 {
-            let actual_pid = getpid();
+            let actual_pid = process::id();
             if require_pid != actual_pid {
                 unsafe {
                     libc::raise(libc::SIGUSR1);
diff --git a/src/test/ui/process/signal-exit-status.rs b/src/test/ui/process/signal-exit-status.rs
new file mode 100644 (file)
index 0000000..0963dcc
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+// ignore-windows
+
+use std::env;
+use std::process::Command;
+
+pub fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() >= 2 && args[1] == "signal" {
+        // Raise a segfault.
+        unsafe { *(1 as *mut isize) = 0; }
+    } else {
+        let status = Command::new(&args[0]).arg("signal").status().unwrap();
+        assert!(status.code().is_none());
+    }
+}
index f53bcb97e69723ad748e710a63deae7916f00876..e8e477ea4f6849aec68d7c03fc9ba2085393a8cb 100644 (file)
@@ -7,6 +7,7 @@
 fn a() {
     // the cast is unreachable:
     let x = {return} as !; //~ ERROR unreachable
+    //~| ERROR non-primitive cast
 }
 
 fn main() { }
index 3aa15bde9956b57bcb1fbf3a9e2e6239b7537264..6643f1784a1744916b10721961130ab320fdc881 100644 (file)
@@ -13,5 +13,12 @@ note: the lint level is defined here
 LL | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error[E0605]: non-primitive cast: `()` as `!`
+  --> $DIR/expr_cast.rs:9:13
+   |
+LL |     let x = {return} as !;
+   |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0605`.
diff --git a/src/test/ui/regions/issue-21520.rs b/src/test/ui/regions/issue-21520.rs
new file mode 100644 (file)
index 0000000..ab4ac72
--- /dev/null
@@ -0,0 +1,22 @@
+// check-pass
+#![allow(dead_code)]
+// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
+// not wind up propagating to `T`.
+
+// pretty-expanded FIXME #23616
+
+pub trait Foo {
+    type Bar;
+
+    fn foo(&self) -> Self;
+}
+
+pub struct Static<T:'static>(T);
+
+struct Bar<T:Foo>
+    where T::Bar : 'static
+{
+    x: Static<Option<T::Bar>>
+}
+
+fn main() { }
diff --git a/src/test/ui/regions/issue-26448-1.rs b/src/test/ui/regions/issue-26448-1.rs
new file mode 100644 (file)
index 0000000..7d2d75b
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+
+pub trait Foo<T> {
+    fn foo(self) -> T;
+}
+
+impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
+    fn foo(self) -> T {
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-26448-2.rs b/src/test/ui/regions/issue-26448-2.rs
new file mode 100644 (file)
index 0000000..c60e06c
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+pub struct Bar<T> {
+    items: Vec<&'static str>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-26448-3.rs b/src/test/ui/regions/issue-26448-3.rs
new file mode 100644 (file)
index 0000000..d48022c
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+
+pub struct Item {
+    _inner: &'static str,
+}
+
+pub struct Bar<T> {
+    items: Vec<Item>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/required-lang-item.rs b/src/test/ui/required-lang-item.rs
deleted file mode 100644 (file)
index 3b17c5b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// build-fail
-
-#![feature(lang_items, no_core)]
-#![no_core]
-
-#[lang="copy"] pub trait Copy { }
-#[lang="sized"] pub trait Sized { }
-
-// error-pattern:requires `start` lang_item
-
-fn main() {}
diff --git a/src/test/ui/required-lang-item.stderr b/src/test/ui/required-lang-item.stderr
deleted file mode 100644 (file)
index 83764a9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-error: requires `start` lang_item
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/resolve/editions-crate-root-2015.rs b/src/test/ui/resolve/editions-crate-root-2015.rs
new file mode 100644 (file)
index 0000000..4c890e3
--- /dev/null
@@ -0,0 +1,21 @@
+// edition:2015
+
+mod inner {
+    fn global_inner(_: ::nonexistant::Foo) {
+        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
+    }
+    fn crate_inner(_: crate::nonexistant::Foo) {
+        //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
+    }
+
+    fn bare_global(_: ::nonexistant) {
+        //~^ ERROR cannot find type `nonexistant` in the crate root
+    }
+    fn bare_crate(_: crate::nonexistant) {
+        //~^ ERROR cannot find type `nonexistant` in the crate root
+    }
+}
+
+fn main() {
+
+}
diff --git a/src/test/ui/resolve/editions-crate-root-2015.stderr b/src/test/ui/resolve/editions-crate-root-2015.stderr
new file mode 100644 (file)
index 0000000..f8d65fe
--- /dev/null
@@ -0,0 +1,28 @@
+error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
+  --> $DIR/editions-crate-root-2015.rs:4:26
+   |
+LL |     fn global_inner(_: ::nonexistant::Foo) {
+   |                          ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+
+error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
+  --> $DIR/editions-crate-root-2015.rs:7:30
+   |
+LL |     fn crate_inner(_: crate::nonexistant::Foo) {
+   |                              ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+
+error[E0412]: cannot find type `nonexistant` in the crate root
+  --> $DIR/editions-crate-root-2015.rs:11:25
+   |
+LL |     fn bare_global(_: ::nonexistant) {
+   |                         ^^^^^^^^^^^ not found in the crate root
+
+error[E0412]: cannot find type `nonexistant` in the crate root
+  --> $DIR/editions-crate-root-2015.rs:14:29
+   |
+LL |     fn bare_crate(_: crate::nonexistant) {
+   |                             ^^^^^^^^^^^ not found in the crate root
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0412, E0433.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/resolve/issue-12796.rs b/src/test/ui/resolve/issue-12796.rs
new file mode 100644 (file)
index 0000000..942d6b9
--- /dev/null
@@ -0,0 +1,9 @@
+trait Trait {
+    fn outer(&self) {
+        fn inner(_: &Self) {
+            //~^ ERROR can't use generic parameters from outer function
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/resolve/issue-12796.stderr b/src/test/ui/resolve/issue-12796.stderr
new file mode 100644 (file)
index 0000000..a01fd2d
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-12796.rs:3:22
+   |
+LL |         fn inner(_: &Self) {
+   |                      ^^^^
+   |                      |
+   |                      use of generic parameter from outer function
+   |                      can't use `Self` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/resolve/issue-23716.rs b/src/test/ui/resolve/issue-23716.rs
new file mode 100644 (file)
index 0000000..e9139c0
--- /dev/null
@@ -0,0 +1,17 @@
+static foo: i32 = 0;
+
+fn bar(foo: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+
+mod submod {
+    pub static answer: i32 = 42;
+}
+
+use self::submod::answer;
+
+fn question(answer: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+fn main() {
+}
diff --git a/src/test/ui/resolve/issue-23716.stderr b/src/test/ui/resolve/issue-23716.stderr
new file mode 100644 (file)
index 0000000..e7bebfb
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0530]: function parameters cannot shadow statics
+  --> $DIR/issue-23716.rs:3:8
+   |
+LL | static foo: i32 = 0;
+   | -------------------- the static `foo` is defined here
+LL | 
+LL | fn bar(foo: i32) {}
+   |        ^^^ cannot be named the same as a static
+
+error[E0530]: function parameters cannot shadow statics
+  --> $DIR/issue-23716.rs:13:13
+   |
+LL | use self::submod::answer;
+   |     -------------------- the static `answer` is imported here
+LL | 
+LL | fn question(answer: i32) {}
+   |             ^^^^^^ cannot be named the same as a static
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/resolve/issue-3021-c.rs b/src/test/ui/resolve/issue-3021-c.rs
new file mode 100644 (file)
index 0000000..94ed1fd
--- /dev/null
@@ -0,0 +1,9 @@
+fn siphash<T>() {
+
+    trait U {
+        fn g(&self, x: T) -> T;  //~ ERROR can't use generic parameters from outer function
+        //~^ ERROR can't use generic parameters from outer function
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-3021-c.stderr b/src/test/ui/resolve/issue-3021-c.stderr
new file mode 100644 (file)
index 0000000..8764ac8
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-3021-c.rs:4:24
+   |
+LL | fn siphash<T>() {
+   |            - type parameter from outer function
+...
+LL |         fn g(&self, x: T) -> T;
+   |            -           ^ use of generic parameter from outer function
+   |            |
+   |            help: try using a local generic parameter instead: `g<T>`
+
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/issue-3021-c.rs:4:30
+   |
+LL | fn siphash<T>() {
+   |            - type parameter from outer function
+...
+LL |         fn g(&self, x: T) -> T;
+   |            -                 ^ use of generic parameter from outer function
+   |            |
+   |            help: try using a local generic parameter instead: `g<T>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/resolve/issue-3021.rs b/src/test/ui/resolve/issue-3021.rs
new file mode 100644 (file)
index 0000000..a672261
--- /dev/null
@@ -0,0 +1,18 @@
+trait SipHash {
+    fn reset(&self);
+}
+
+fn siphash(k0 : u64) {
+    struct SipState {
+        v0: u64,
+    }
+
+    impl SipHash for SipState {
+        fn reset(&self) {
+           self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
+        }
+    }
+    panic!();
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-3021.stderr b/src/test/ui/resolve/issue-3021.stderr
new file mode 100644 (file)
index 0000000..d5b015e
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0434]: can't capture dynamic environment in a fn item
+  --> $DIR/issue-3021.rs:12:22
+   |
+LL |            self.v0 = k0 ^ 0x736f6d6570736575;
+   |                      ^^
+   |
+   = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
diff --git a/src/test/ui/resolve/issue-31845.rs b/src/test/ui/resolve/issue-31845.rs
new file mode 100644 (file)
index 0000000..f6dc115
--- /dev/null
@@ -0,0 +1,12 @@
+// Checks lexical scopes cannot see through normal module boundaries
+
+fn f() {
+    fn g() {}
+    mod foo {
+        fn h() {
+           g(); //~ ERROR cannot find function `g` in this scope
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-31845.stderr b/src/test/ui/resolve/issue-31845.stderr
new file mode 100644 (file)
index 0000000..5628193
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `g` in this scope
+  --> $DIR/issue-31845.rs:7:12
+   |
+LL |            g();
+   |            ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-5099.rs b/src/test/ui/resolve/issue-5099.rs
new file mode 100644 (file)
index 0000000..b5abccb
--- /dev/null
@@ -0,0 +1,13 @@
+trait B <A> {
+    fn a() -> A {
+        this.a //~ ERROR cannot find value `this` in this scope
+    }
+    fn b(x: i32) {
+        this.b(x); //~ ERROR cannot find value `this` in this scope
+    }
+    fn c() {
+        let _ = || this.a; //~ ERROR cannot find value `this` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-5099.stderr b/src/test/ui/resolve/issue-5099.stderr
new file mode 100644 (file)
index 0000000..e9b2a9c
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:3:9
+   |
+LL |         this.a
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.a
+   |         ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn a(&self) -> A {
+   |          +++++
+
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:6:9
+   |
+LL |         this.b(x);
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.b(x);
+   |         ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn b(&self, x: i32) {
+   |          ++++++
+
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:9:20
+   |
+LL |         let _ = || this.a;
+   |                    ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         let _ = || self.a;
+   |                    ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn c(&self) {
+   |          +++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs
new file mode 100644 (file)
index 0000000..0260caa
--- /dev/null
@@ -0,0 +1,21 @@
+// Matching against NaN should result in a warning
+
+#![allow(unused)]
+#![deny(illegal_floating_point_literal_pattern)]
+
+const NAN: f64 = f64::NAN;
+
+fn main() {
+    let x = NAN;
+    match x {
+        NAN => {}, //~ ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+
+    match [x, 1.0] {
+        [NAN, _] => {}, //~ ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+}
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
new file mode 100644 (file)
index 0000000..4e2961e
--- /dev/null
@@ -0,0 +1,25 @@
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:11:9
+   |
+LL |         NAN => {},
+   |         ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-6804.rs:4:9
+   |
+LL | #![deny(illegal_floating_point_literal_pattern)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:17:10
+   |
+LL |         [NAN, _] => {},
+   |          ^^^
+   |
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 2 previous errors
+
index 4b2f049b99d9e05063772574e45b0b1f2e34a63c..961968186de24a520918bcee881ed1344de12c46 100644 (file)
@@ -2,9 +2,8 @@
 
 pub struct Int(i32);
 
-impl const std::ops::Add for i32 {
-    //~^ ERROR conflicting implementations of trait
-    //~| ERROR only traits defined in the current crate can be implemented for arbitrary types
+impl const std::ops::Add for i32 { //~ ERROR type annotations needed
+    //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
@@ -12,7 +11,7 @@ fn add(self, rhs: Self) -> Self {
     }
 }
 
-impl std::ops::Add for Int {
+impl std::ops::Add for Int { //~ ERROR type annotations needed
     type Output = Self;
 
     fn add(self, rhs: Self) -> Self {
@@ -20,7 +19,7 @@ fn add(self, rhs: Self) -> Self {
     }
 }
 
-impl const std::ops::Add for Int {
+impl const std::ops::Add for Int { //~ ERROR type annotations needed
     //~^ ERROR conflicting implementations of trait
     type Output = Self;
 
index a0960a21d46f87e1c45420e6911e85ba61bce4df..785095c29ae4ebc8e886f96583285bbd08994615 100644 (file)
@@ -1,14 +1,17 @@
-error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32`
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/const-and-non-const-impl.rs:5:1
    |
 LL | impl const std::ops::Add for i32 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^-------------^^^^^---
+   | |          |                 |
+   | |          |                 `i32` is not defined in the current crate
+   | |          `i32` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
    |
-   = note: conflicting implementation in crate `core`:
-           - impl Add for i32;
+   = note: define and implement a trait or new type instead
 
 error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int`
-  --> $DIR/const-and-non-const-impl.rs:23:1
+  --> $DIR/const-and-non-const-impl.rs:22:1
    |
 LL | impl std::ops::Add for Int {
    | -------------------------- first implementation here
@@ -16,19 +19,83 @@ LL | impl std::ops::Add for Int {
 LL | impl const std::ops::Add for Int {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
 
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0283]: type annotations needed
+  --> $DIR/const-and-non-const-impl.rs:5:12
+   |
+LL | impl const std::ops::Add for i32 {
+   |            ^^^^^^^^^^^^^ cannot infer type for type `i32`
+   |
+note: multiple `impl`s satisfying `i32: Add` found
   --> $DIR/const-and-non-const-impl.rs:5:1
    |
 LL | impl const std::ops::Add for i32 {
-   | ^^^^^^^^^^^-------------^^^^^---
-   | |          |                 |
-   | |          |                 `i32` is not defined in the current crate
-   | |          `i32` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: and another `impl` found in the `core` crate: `impl Add for i32;`
+note: required by a bound in `Add`
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
    |
-   = note: define and implement a trait or new type instead
+LL | / pub trait Add<Rhs = Self> {
+LL | |     /// The resulting type after applying the `+` operator.
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     type Output;
+...  |
+LL | |     fn add(self, rhs: Rhs) -> Self::Output;
+LL | | }
+   | |_^ required by this bound in `Add`
+
+error[E0283]: type annotations needed
+  --> $DIR/const-and-non-const-impl.rs:14:6
+   |
+LL | impl std::ops::Add for Int {
+   |      ^^^^^^^^^^^^^ cannot infer type for struct `Int`
+   |
+note: multiple `impl`s satisfying `Int: Add` found
+  --> $DIR/const-and-non-const-impl.rs:14:1
+   |
+LL | impl std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl const std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `Add`
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+   |
+LL | / pub trait Add<Rhs = Self> {
+LL | |     /// The resulting type after applying the `+` operator.
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     type Output;
+...  |
+LL | |     fn add(self, rhs: Rhs) -> Self::Output;
+LL | | }
+   | |_^ required by this bound in `Add`
+
+error[E0283]: type annotations needed
+  --> $DIR/const-and-non-const-impl.rs:22:12
+   |
+LL | impl const std::ops::Add for Int {
+   |            ^^^^^^^^^^^^^ cannot infer type for struct `Int`
+   |
+note: multiple `impl`s satisfying `Int: Add` found
+  --> $DIR/const-and-non-const-impl.rs:14:1
+   |
+LL | impl std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl const std::ops::Add for Int {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `Add`
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
+   |
+LL | / pub trait Add<Rhs = Self> {
+LL | |     /// The resulting type after applying the `+` operator.
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     type Output;
+...  |
+LL | |     fn add(self, rhs: Rhs) -> Self::Output;
+LL | | }
+   | |_^ required by this bound in `Add`
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0117, E0119.
+Some errors have detailed explanations: E0117, E0119, E0283.
 For more information about an error, try `rustc --explain E0117`.
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs
new file mode 100644 (file)
index 0000000..1e8b99b
--- /dev/null
@@ -0,0 +1,29 @@
+// gate-test-type_changing_struct_update
+
+#[derive(Debug)]
+struct Machine<S> {
+    state: S,
+    common_field1: &'static str,
+    common_field2: i32,
+}
+#[derive(Debug)]
+struct State1;
+#[derive(Debug, PartialEq)]
+struct State2;
+
+fn update_to_state2() {
+    let m1: Machine<State1> = Machine {
+        state: State1,
+        common_field1: "hello",
+        common_field2: 2,
+    };
+    let m2: Machine<State2> = Machine {
+        state: State2,
+        ..m1
+        //~^ ERROR type changing struct updating is experimental [E0658]
+        //~| ERROR mismatched types [E0308]
+    };
+    assert_eq!(State2, m2.state);
+}
+
+fn main() {}
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr
new file mode 100644 (file)
index 0000000..2217b8c
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0658]: type changing struct updating is experimental
+  --> $DIR/feature-gate.rs:22:11
+   |
+LL |         ..m1
+   |           ^^
+   |
+   = note: see issue #86555 <https://github.com/rust-lang/rust/issues/86555> for more information
+   = help: add `#![feature(type_changing_struct_update)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate.rs:22:11
+   |
+LL |         ..m1
+   |           ^^ expected struct `State2`, found struct `State1`
+   |
+   = note: expected struct `Machine<State2>`
+              found struct `Machine<State1>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs
new file mode 100644 (file)
index 0000000..df2fef5
--- /dev/null
@@ -0,0 +1,43 @@
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+#[derive(Clone)]
+struct Machine<'a, S> {
+    state: S,
+    lt_str: &'a str,
+    common_field: i32,
+}
+
+#[derive(Clone)]
+struct State1;
+#[derive(Clone)]
+struct State2;
+
+fn update_to_state2() {
+    let s = String::from("hello");
+    let m1: Machine<State1> = Machine {
+        state: State1,
+        lt_str: &s,
+                //~^ ERROR `s` does not live long enough [E0597]
+                // FIXME: The error here actually comes from line 34. The
+                // span of the error message should be corrected to line 34
+        common_field: 2,
+    };
+    // update lifetime
+    let m3: Machine<'static, State1> = Machine {
+        lt_str: "hello, too",
+        ..m1.clone()
+    };
+    // update lifetime and type
+    let m4: Machine<'static, State2> = Machine {
+        state: State2,
+        lt_str: "hello, again",
+        ..m1.clone()
+    };
+    // updating to `static should fail.
+    let m2: Machine<'static, State1> = Machine {
+        ..m1
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
new file mode 100644 (file)
index 0000000..5f93ad6
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/lifetime-update.rs:20:17
+   |
+LL |         lt_str: &s,
+   |                 ^^ borrowed value does not live long enough
+...
+LL |     let m2: Machine<'static, State1> = Machine {
+   |             ------------------------ type annotation requires that `s` is borrowed for `'static`
+...
+LL | }
+   | - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs
new file mode 100644 (file)
index 0000000..d8b1396
--- /dev/null
@@ -0,0 +1,57 @@
+#![feature(type_changing_struct_update)]
+#![allow(incomplete_features)]
+
+struct Machine<'a, S, M> {
+    state: S,
+    message: M,
+    lt_str: &'a str,
+    common_field: i32,
+}
+
+struct State1;
+struct State2;
+
+struct Message1;
+struct Message2;
+
+fn update() {
+    let m1: Machine<State1, Message1> = Machine {
+        state: State1,
+        message: Message1,
+        lt_str: "hello",
+        common_field: 2,
+    };
+    // single type update
+    let m2: Machine<State2, Message1> = Machine {
+        state: State2,
+        ..m1
+    };
+    // multiple type update
+    let m3: Machine<State2, Message2> = Machine {
+        state: State2,
+        message: Message2,
+        ..m1
+    };
+}
+
+fn fail_update() {
+    let m1: Machine<f64, f64> = Machine {
+        state: 3.2,
+        message: 6.4,
+        lt_str: "hello",
+        common_field: 2,
+    };
+    // single type update fail
+    let m2: Machine<i32, f64> = Machine {
+        ..m1
+        //~^ ERROR mismatched types [E0308]
+    };
+    // multiple type update fail
+    let m3 = Machine::<i32, i32> {
+        ..m1
+        //~^ ERROR mismatched types [E0308]
+        //~| ERROR mismatched types [E0308]
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/src/test/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr
new file mode 100644 (file)
index 0000000..fa8d6ee
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/type-generic-update.rs:46:11
+   |
+LL |         ..m1
+   |           ^^ field type mismatch: Machine.state
+   |
+   = note: expected type `i32`
+              found type `f64`
+
+error[E0308]: mismatched types
+  --> $DIR/type-generic-update.rs:51:11
+   |
+LL |         ..m1
+   |           ^^ field type mismatch: Machine.state
+   |
+   = note: expected type `i32`
+              found type `f64`
+
+error[E0308]: mismatched types
+  --> $DIR/type-generic-update.rs:51:11
+   |
+LL |         ..m1
+   |           ^^ field type mismatch: Machine.message
+   |
+   = note: expected type `i32`
+              found type `f64`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/self/issue-61882-2.rs b/src/test/ui/self/issue-61882-2.rs
new file mode 100644 (file)
index 0000000..1209b54
--- /dev/null
@@ -0,0 +1,11 @@
+struct A<T>(T);
+
+impl A<&'static u8> {
+    fn f() {
+        let x = 0;
+        Self(&x);
+        //~^ ERROR `x` does not live long enough
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/self/issue-61882-2.stderr b/src/test/ui/self/issue-61882-2.stderr
new file mode 100644 (file)
index 0000000..0b8e134
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/issue-61882-2.rs:6:14
+   |
+LL |         Self(&x);
+   |              ^^
+   |              |
+   |              borrowed value does not live long enough
+   |              this usage requires that `x` is borrowed for `'static`
+LL |
+LL |     }
+   |     - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/self/issue-61882.rs b/src/test/ui/self/issue-61882.rs
new file mode 100644 (file)
index 0000000..013398b
--- /dev/null
@@ -0,0 +1,9 @@
+struct A<T>(T);
+
+impl A<bool> {
+    const B: A<u8> = Self(0);
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/self/issue-61882.stderr b/src/test/ui/self/issue-61882.stderr
new file mode 100644 (file)
index 0000000..09ffe8e
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-61882.rs:4:27
+   |
+LL |     const B: A<u8> = Self(0);
+   |                           ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/issue-61882.rs:4:22
+   |
+LL |     const B: A<u8> = Self(0);
+   |                      ^^^^^^^ expected `u8`, found `bool`
+   |
+   = note: expected struct `A<u8>`
+              found struct `A<bool>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/signal-exit-status.rs b/src/test/ui/signal-exit-status.rs
deleted file mode 100644 (file)
index 0963dcc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-pass
-// ignore-emscripten no processes
-// ignore-sgx no processes
-// ignore-windows
-
-use std::env;
-use std::process::Command;
-
-pub fn main() {
-    let args: Vec<String> = env::args().collect();
-    if args.len() >= 2 && args[1] == "signal" {
-        // Raise a segfault.
-        unsafe { *(1 as *mut isize) = 0; }
-    } else {
-        let status = Command::new(&args[0]).arg("signal").status().unwrap();
-        assert!(status.code().is_none());
-    }
-}
index 92c4e67dfdd1961b68adaf7b54df1b03dfdec5ef..9a23dae77b96e572084b590f04cb27b943dbc9f7 100644 (file)
@@ -51,19 +51,19 @@ fn main() {
         let _: u64 = simd_bitmask(m64);
 
         let _: u16 = simd_bitmask(m2);
-        //~^ ERROR bitmask `u16`, expected `u8`
+        //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
 
         let _: u16 = simd_bitmask(m8);
-        //~^ ERROR bitmask `u16`, expected `u8`
+        //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
 
         let _: u32 = simd_bitmask(m16);
-        //~^ ERROR bitmask `u32`, expected `u16`
+        //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
 
         let _: u64 = simd_bitmask(m32);
-        //~^ ERROR bitmask `u64`, expected `u32`
+        //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
 
         let _: u128 = simd_bitmask(m64);
-        //~^ ERROR bitmask `u128`, expected `u64`
+        //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic
 
    }
 }
index 5aaae68cafb342501e769ee7a9d8326873a61b8e..0de3f8eead86d12bf3fdb18e3e8e1d9ad1a70d4b 100644 (file)
@@ -1,28 +1,28 @@
-error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]`
   --> $DIR/generic-bitmask.rs:53:22
    |
 LL |         let _: u16 = simd_bitmask(m2);
    |                      ^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8`
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]`
   --> $DIR/generic-bitmask.rs:56:22
    |
 LL |         let _: u16 = simd_bitmask(m8);
    |                      ^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16`
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u32`, expected `u16` or `[u8; 2]`
   --> $DIR/generic-bitmask.rs:59:22
    |
 LL |         let _: u32 = simd_bitmask(m16);
    |                      ^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32`
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u64`, expected `u32` or `[u8; 4]`
   --> $DIR/generic-bitmask.rs:62:22
    |
 LL |         let _: u64 = simd_bitmask(m32);
    |                      ^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64`
+error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u128`, expected `u64` or `[u8; 8]`
   --> $DIR/generic-bitmask.rs:65:23
    |
 LL |         let _: u128 = simd_bitmask(m64);
index 7d68af49e2868a8d76c38be186921451c784d739..248e82ea21cfce6ec8aefcbb44b0ca8c093cfc46 100644 (file)
@@ -20,8 +20,7 @@
 
 #[repr(simd)]
 #[derive(Copy, Clone, PartialEq)]
-struct b8x8(pub i8, pub i8, pub i8, pub i8,
-            pub i8, pub i8, pub i8, pub i8);
+struct b8x8(pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8);
 
 extern "platform-intrinsic" {
     fn simd_select<T, U>(x: T, a: U, b: U) -> U;
@@ -50,15 +49,15 @@ fn main() {
         //~^ ERROR found non-SIMD `u32`
 
         simd_select_bitmask(0u16, x, x);
-        //~^ ERROR mask length `16` != other vector length `4`
-        //
+        //~^ ERROR invalid bitmask `u16`, expected `u8` or `[u8; 1]`
+
         simd_select_bitmask(0u8, 1u32, 2u32);
         //~^ ERROR found non-SIMD `u32`
 
         simd_select_bitmask(0.0f32, x, x);
-        //~^ ERROR `f32` is not an integral type
+        //~^ ERROR invalid bitmask `f32`, expected `u8` or `[u8; 1]`
 
         simd_select_bitmask("x", x, x);
-        //~^ ERROR `&str` is not an integral type
+        //~^ ERROR invalid bitmask `&str`, expected `u8` or `[u8; 1]`
     }
 }
index c53d581745a7c4227249f7c3677ce12258250a30..d576f1bc77473fc2216b3cfe28ffe3a84d75fc15 100644 (file)
@@ -1,47 +1,47 @@
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4`
-  --> $DIR/generic-select.rs:40:9
+  --> $DIR/generic-select.rs:39:9
    |
 LL |         simd_select(m8, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_`
-  --> $DIR/generic-select.rs:43:9
+  --> $DIR/generic-select.rs:42:9
    |
 LL |         simd_select(x, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_`
-  --> $DIR/generic-select.rs:46:9
+  --> $DIR/generic-select.rs:45:9
    |
 LL |         simd_select(z, z, z);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
-  --> $DIR/generic-select.rs:49:9
+  --> $DIR/generic-select.rs:48:9
    |
 LL |         simd_select(m4, 0u32, 1u32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: mismatched lengths: mask length `16` != other vector length `4`
-  --> $DIR/generic-select.rs:52:9
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `u16`, expected `u8` or `[u8; 1]`
+  --> $DIR/generic-select.rs:51:9
    |
 LL |         simd_select_bitmask(0u16, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
-  --> $DIR/generic-select.rs:55:9
+  --> $DIR/generic-select.rs:54:9
    |
 LL |         simd_select_bitmask(0u8, 1u32, 2u32);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type
-  --> $DIR/generic-select.rs:58:9
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `f32`, expected `u8` or `[u8; 1]`
+  --> $DIR/generic-select.rs:57:9
    |
 LL |         simd_select_bitmask(0.0f32, x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `&str` is not an integral type
-  --> $DIR/generic-select.rs:61:9
+error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `&str`, expected `u8` or `[u8; 1]`
+  --> $DIR/generic-select.rs:60:9
    |
 LL |         simd_select_bitmask("x", x, x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/simd/libm_no_std_cant_float.rs b/src/test/ui/simd/libm_no_std_cant_float.rs
new file mode 100644 (file)
index 0000000..abe460a
--- /dev/null
@@ -0,0 +1,21 @@
+#![crate_type = "rlib"]
+#![no_std]
+#![feature(portable_simd)]
+use core::simd::f32x4;
+
+// For SIMD float ops, the LLIR version which is used to implement the portable
+// forms of them may become calls to math.h AKA libm. So, we can't guarantee
+// we can compile them for #![no_std] crates.
+// Someday we may solve this.
+// Until then, this test at least guarantees these functions require std.
+fn guarantee_no_std_nolibm_calls() -> f32x4 {
+    let x = f32x4::from_array([0.1, 0.5, 0.6, -1.5]);
+    let x2 = x + x;
+    let _xc = x.ceil(); //~ ERROR E0599
+    let _xf = x.floor(); //~ ERROR E0599
+    let _xr = x.round(); //~ ERROR E0599
+    let _xt = x.trunc(); //~ ERROR E0599
+    let _xfma = x.mul_add(x, x); //~ ERROR E0599
+    let _xsqrt = x.sqrt(); //~ ERROR E0599
+    x2.abs() * x2
+}
diff --git a/src/test/ui/simd/libm_no_std_cant_float.stderr b/src/test/ui/simd/libm_no_std_cant_float.stderr
new file mode 100644 (file)
index 0000000..dc8638f
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0599]: no method named `ceil` found for struct `Simd` in the current scope
+  --> $DIR/libm_no_std_cant_float.rs:14:17
+   |
+LL |     let _xc = x.ceil();
+   |                 ^^^^ method not found in `Simd<f32, 4_usize>`
+
+error[E0599]: no method named `floor` found for struct `Simd` in the current scope
+  --> $DIR/libm_no_std_cant_float.rs:15:17
+   |
+LL |     let _xf = x.floor();
+   |                 ^^^^^ method not found in `Simd<f32, 4_usize>`
+
+error[E0599]: no method named `round` found for struct `Simd` in the current scope
+  --> $DIR/libm_no_std_cant_float.rs:16:17
+   |
+LL |     let _xr = x.round();
+   |                 ^^^^^ method not found in `Simd<f32, 4_usize>`
+
+error[E0599]: no method named `trunc` found for struct `Simd` in the current scope
+  --> $DIR/libm_no_std_cant_float.rs:17:17
+   |
+LL |     let _xt = x.trunc();
+   |                 ^^^^^ method not found in `Simd<f32, 4_usize>`
+
+error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope
+  --> $DIR/libm_no_std_cant_float.rs:18:19
+   |
+LL |     let _xfma = x.mul_add(x, x);
+   |                   ^^^^^^^ method not found in `Simd<f32, 4_usize>`
+
+error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope
+  --> $DIR/libm_no_std_cant_float.rs:19:20
+   |
+LL |     let _xsqrt = x.sqrt();
+   |                    ^^^^ method not found in `Simd<f32, 4_usize>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/simd/portable-intrinsics-arent-exposed.rs b/src/test/ui/simd/portable-intrinsics-arent-exposed.rs
new file mode 100644 (file)
index 0000000..4d75903
--- /dev/null
@@ -0,0 +1,8 @@
+// May not matter, since people can use them with a nightly feature.
+// However this tests to guarantee they don't leak out via portable_simd,
+// and thus don't accidentally get stabilized.
+use std::simd::intrinsics; //~ERROR E0603
+
+fn main() {
+    ()
+}
diff --git a/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr b/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr
new file mode 100644 (file)
index 0000000..9ac73ec
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0603]: module `intrinsics` is private
+  --> $DIR/portable-intrinsics-arent-exposed.rs:4:16
+   |
+LL | use std::simd::intrinsics;
+   |                ^^^^^^^^^^ private module
+   |
+note: the module `intrinsics` is defined here
+  --> $SRC_DIR/core/src/lib.rs:LL:COL
+   |
+LL |     pub use crate::core_simd::simd::*;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/simd/simd-bitmask.rs b/src/test/ui/simd/simd-bitmask.rs
new file mode 100644 (file)
index 0000000..14ee2e7
--- /dev/null
@@ -0,0 +1,52 @@
+//run-pass
+//ignore-endian-big behavior of simd_select_bitmask is endian-specific
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_bitmask<T, U>(v: T) -> U;
+    fn simd_select_bitmask<T, U>(m: T, a: U, b: U) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+fn main() {
+    unsafe {
+        let v = Simd::<i8, 4>([-1, 0, -1, 0]);
+        let i: u8 = simd_bitmask(v);
+        let a: [u8; 1] = simd_bitmask(v);
+
+        assert_eq!(i, 0b0101);
+        assert_eq!(a, [0b0101]);
+
+        let v = Simd::<i8, 16>([0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0]);
+        let i: u16 = simd_bitmask(v);
+        let a: [u8; 2] = simd_bitmask(v);
+
+        assert_eq!(i, 0b0101000000001100);
+        assert_eq!(a, [0b1100, 0b01010000]);
+    }
+
+    unsafe {
+        let a = Simd::<i32, 8>([0, 1, 2, 3, 4, 5, 6, 7]);
+        let b = Simd::<i32, 8>([8, 9, 10, 11, 12, 13, 14, 15]);
+        let e = [0, 9, 2, 11, 12, 13, 14, 15];
+
+        let r = simd_select_bitmask(0b0101u8, a, b);
+        assert_eq!(r.0, e);
+
+        let r = simd_select_bitmask([0b0101u8], a, b);
+        assert_eq!(r.0, e);
+
+        let a = Simd::<i32, 16>([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
+        let b = Simd::<i32, 16>([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]);
+        let e = [16, 17, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 12, 29, 14, 31];
+
+        let r = simd_select_bitmask(0b0101000000001100u16, a, b);
+        assert_eq!(r.0, e);
+
+        let r = simd_select_bitmask([0b1100u8, 0b01010000u8], a, b);
+        assert_eq!(r.0, e);
+    }
+}
diff --git a/src/test/ui/specialization/transmute-specialization.rs b/src/test/ui/specialization/transmute-specialization.rs
new file mode 100644 (file)
index 0000000..499334d
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Specializable { type Output; }
+
+impl<T> Specializable for T {
+    default type Output = u16;
+}
+
+fn main() {
+    unsafe {
+        std::mem::transmute::<u16, <() as Specializable>::Output>(0);
+    }
+}
diff --git a/src/test/ui/specialization/transmute-specialization.stderr b/src/test/ui/specialization/transmute-specialization.stderr
new file mode 100644 (file)
index 0000000..a0ea724
--- /dev/null
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/transmute-specialization.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
index 656564fc9e3f8240d66f64182bd4f4e955a47499..ce2726ffde48737c93ce3f6e36804c3d2e8f3d0b 100644 (file)
@@ -1,27 +1,28 @@
 #![feature(staged_api)]
+//~^ ERROR module has missing stability attribute
 
-#[stable(feature = "x", since = "1")]
+#[stable(feature = "a", since = "1")]
 struct StableType;
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "b", issue = "none")]
 struct UnstableType;
 
-#[stable(feature = "x", since = "1")]
+#[stable(feature = "c", since = "1")]
 trait StableTrait {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "d", issue = "none")]
 trait UnstableTrait {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "e", issue = "none")]
 impl UnstableTrait for UnstableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "f", issue = "none")]
 impl StableTrait for UnstableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "g", issue = "none")]
 impl UnstableTrait for StableType {}
 
-#[unstable(feature = "x", issue = "none")]
+#[unstable(feature = "h", issue = "none")]
 //~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl]
 impl StableTrait for StableType {}
 
index a11479cc8f45cdba0c33c82bbdb8c74776c8ed9d..310f02024ca0a02b6f1a5e0e2eb5841fa9d3ed15 100644 (file)
@@ -1,11 +1,23 @@
 error: an `#[unstable]` annotation here has no effect
-  --> $DIR/stability-attribute-trait-impl.rs:24:1
+  --> $DIR/stability-attribute-trait-impl.rs:25:1
    |
-LL | #[unstable(feature = "x", issue = "none")]
+LL | #[unstable(feature = "h", issue = "none")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[deny(ineffective_unstable_trait_impl)]` on by default
    = note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
 
-error: aborting due to previous error
+error: module has missing stability attribute
+  --> $DIR/stability-attribute-trait-impl.rs:1:1
+   |
+LL | / #![feature(staged_api)]
+LL | |
+LL | |
+LL | | #[stable(feature = "a", since = "1")]
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/static/auxiliary/nested_item.rs b/src/test/ui/static/auxiliary/nested_item.rs
new file mode 100644 (file)
index 0000000..9db9d19
--- /dev/null
@@ -0,0 +1,30 @@
+// original problem
+pub fn foo<T>() -> isize {
+    {
+        static foo: isize = 2;
+        foo
+    }
+}
+
+// issue 8134
+struct Foo;
+impl Foo {
+    pub fn foo<T>(&self) {
+        static X: usize = 1;
+    }
+}
+
+// issue 8134
+pub struct Parser<T>(T);
+impl<T: std::iter::Iterator<Item=char>> Parser<T> {
+    fn in_doctype(&mut self) {
+        static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
+    }
+}
+
+struct Bar;
+impl Foo {
+    pub fn bar<T>(&self) {
+        static X: usize = 1;
+    }
+}
diff --git a/src/test/ui/static/nested_item_main.rs b/src/test/ui/static/nested_item_main.rs
new file mode 100644 (file)
index 0000000..2fe00ae
--- /dev/null
@@ -0,0 +1,10 @@
+// run-pass
+// aux-build:nested_item.rs
+
+
+extern crate nested_item;
+
+pub fn main() {
+    assert_eq!(2, nested_item::foo::<()>());
+    assert_eq!(2, nested_item::foo::<isize>());
+}
diff --git a/src/test/ui/statics/issue-14227.mir.stderr b/src/test/ui/statics/issue-14227.mir.stderr
new file mode 100644 (file)
index 0000000..8e7a251
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-14227.rs:7:21
+   |
+LL | static CRASH: u32 = symbol;
+   |                     ^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/statics/issue-14227.rs b/src/test/ui/statics/issue-14227.rs
new file mode 100644 (file)
index 0000000..5f866ec
--- /dev/null
@@ -0,0 +1,10 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+extern "C" {
+    pub static symbol: u32;
+}
+static CRASH: u32 = symbol;
+//~^ ERROR use of extern static is unsafe and requires
+
+fn main() {}
diff --git a/src/test/ui/statics/issue-14227.thir.stderr b/src/test/ui/statics/issue-14227.thir.stderr
new file mode 100644 (file)
index 0000000..8e7a251
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+  --> $DIR/issue-14227.rs:7:21
+   |
+LL | static CRASH: u32 = symbol;
+   |                     ^^^^^^ use of extern static
+   |
+   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
index cc78f6cfa53f7127282038e0aaf1990424e8812f..d5645474891062e2a43bddacdcf8fbe0ab450e7f 100644 (file)
@@ -11,7 +11,11 @@ enum Void {}
 
 static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
+//~| ERROR undefined behavior to use this value
+//~| WARN: type `Void` does not permit zero-initialization
 static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
 //~| WARN: previously accepted
+//~| ERROR undefined behavior to use this value
+//~| WARN: type `Void` does not permit zero-initialization
 
 fn main() {}
index 5d95b29993827ff6b005f528373bafb9b35dc452..c38cf10d6e648bfad53cb16009a3d2c4c5759329 100644 (file)
@@ -34,7 +34,7 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
 
 error: static of uninhabited type
-  --> $DIR/uninhabited-static.rs:14:1
+  --> $DIR/uninhabited-static.rs:16:1
    |
 LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,5 +43,47 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
    = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
    = note: uninhabited statics cannot be initialized, and any access would be an immediate error
 
-error: aborting due to 4 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/uninhabited-static.rs:12:1
+   |
+LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 0, align: 1) {}
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/uninhabited-static.rs:16:1
+   |
+LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+   = note: the raw bytes of the constant (size: 0, align: 1) {}
+
+warning: the type `Void` does not permit zero-initialization
+  --> $DIR/uninhabited-static.rs:12:31
+   |
+LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^
+   |                               |
+   |                               this code causes undefined behavior when executed
+   |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: `#[warn(invalid_value)]` on by default
+   = note: enums with no variants have no valid value
+
+warning: the type `Void` does not permit zero-initialization
+  --> $DIR/uninhabited-static.rs:16:32
+   |
+LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^
+   |                                |
+   |                                this code causes undefined behavior when executed
+   |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: enums with no variants have no valid value
+
+error: aborting due to 6 previous errors; 2 warnings emitted
 
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/structs-enums/issue-50731.rs b/src/test/ui/structs-enums/issue-50731.rs
new file mode 100644 (file)
index 0000000..209c1e1
--- /dev/null
@@ -0,0 +1,6 @@
+// run-pass
+enum Void {}
+fn foo(_: Result<(Void, u32), (Void, String)>) {}
+fn main() {
+    let _: fn(_) = foo;
+}
index cc6412e271a132825e6498267211a4e0235d1468..3bc2d16cf9df2a3c09b7a9f3bd3b0c44d90390b2 100644 (file)
@@ -36,6 +36,7 @@ struct Outer {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
diff --git a/src/test/ui/structured-compare.rs b/src/test/ui/structured-compare.rs
deleted file mode 100644 (file)
index 63d30c4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-
-#![allow(non_camel_case_types)]
-
-
-#[derive(Copy, Clone, Debug)]
-enum foo { large, small, }
-
-impl PartialEq for foo {
-    fn eq(&self, other: &foo) -> bool {
-        ((*self) as usize) == ((*other) as usize)
-    }
-    fn ne(&self, other: &foo) -> bool { !(*self).eq(other) }
-}
-
-pub fn main() {
-    let a = (1, 2, 3);
-    let b = (1, 2, 3);
-    assert_eq!(a, b);
-    assert!((a != (1, 2, 4)));
-    assert!((a < (1, 2, 4)));
-    assert!((a <= (1, 2, 4)));
-    assert!(((1, 2, 4) > a));
-    assert!(((1, 2, 4) >= a));
-    let x = foo::large;
-    let y = foo::small;
-    assert!((x != y));
-    assert_eq!(x, foo::large);
-    assert!((x != foo::small));
-}
diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs
new file mode 100644 (file)
index 0000000..d8f7fac
--- /dev/null
@@ -0,0 +1,16 @@
+enum Ty {
+    Unit,
+    List(Box<Ty>),
+}
+
+fn foo(x: Ty) -> Ty {
+    match x {
+        Ty::Unit => Ty::Unit,
+        Ty::List(elem) => foo(elem),
+        //~^ ERROR mismatched types
+        //~| HELP try dereferencing the `Box`
+        //~| HELP try using a variant of the expected enum
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr
new file mode 100644 (file)
index 0000000..d4ccb2c
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/boxed-variant-field.rs:9:31
+   |
+LL |         Ty::List(elem) => foo(elem),
+   |                               ^^^^ expected enum `Ty`, found struct `Box`
+   |
+   = note: expected enum `Ty`
+            found struct `Box<Ty>`
+help: try dereferencing the `Box`
+   |
+LL |         Ty::List(elem) => foo(*elem),
+   |                               +
+help: try using a variant of the expected enum
+   |
+LL |         Ty::List(elem) => foo(Ty::List(elem)),
+   |                               ~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index 355f2038df889ebf4e8c410b41182ce8d7fdbc90..7972437771399f71f356ad3d222c0b7cb0921263 100644 (file)
@@ -4,6 +4,9 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
 LL |     let _: &[i8] = data.into();
    |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
+   = help: the following implementations were found:
+             <[T; LANES] as From<Simd<T, LANES>>>
+             <[bool; LANES] as From<Mask<T, LANES>>>
    = note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]`
 
 error: aborting due to previous error
diff --git a/src/test/ui/supported-cast.rs b/src/test/ui/supported-cast.rs
deleted file mode 100644 (file)
index ff41ce6..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-// run-pass
-
-pub fn main() {
-  let f = 1_usize as *const String;
-  println!("{:?}", f as isize);
-  println!("{:?}", f as usize);
-  println!("{:?}", f as i8);
-  println!("{:?}", f as i16);
-  println!("{:?}", f as i32);
-  println!("{:?}", f as i64);
-  println!("{:?}", f as u8);
-  println!("{:?}", f as u16);
-  println!("{:?}", f as u32);
-  println!("{:?}", f as u64);
-
-  println!("{:?}", 1 as isize);
-  println!("{:?}", 1 as usize);
-  println!("{:?}", 1 as *const String);
-  println!("{:?}", 1 as i8);
-  println!("{:?}", 1 as i16);
-  println!("{:?}", 1 as i32);
-  println!("{:?}", 1 as i64);
-  println!("{:?}", 1 as u8);
-  println!("{:?}", 1 as u16);
-  println!("{:?}", 1 as u32);
-  println!("{:?}", 1 as u64);
-  println!("{:?}", 1 as f32);
-  println!("{:?}", 1 as f64);
-
-  println!("{:?}", 1_usize as isize);
-  println!("{:?}", 1_usize as usize);
-  println!("{:?}", 1_usize as *const String);
-  println!("{:?}", 1_usize as i8);
-  println!("{:?}", 1_usize as i16);
-  println!("{:?}", 1_usize as i32);
-  println!("{:?}", 1_usize as i64);
-  println!("{:?}", 1_usize as u8);
-  println!("{:?}", 1_usize as u16);
-  println!("{:?}", 1_usize as u32);
-  println!("{:?}", 1_usize as u64);
-  println!("{:?}", 1_usize as f32);
-  println!("{:?}", 1_usize as f64);
-
-  println!("{:?}", 1i8 as isize);
-  println!("{:?}", 1i8 as usize);
-  println!("{:?}", 1i8 as *const String);
-  println!("{:?}", 1i8 as i8);
-  println!("{:?}", 1i8 as i16);
-  println!("{:?}", 1i8 as i32);
-  println!("{:?}", 1i8 as i64);
-  println!("{:?}", 1i8 as u8);
-  println!("{:?}", 1i8 as u16);
-  println!("{:?}", 1i8 as u32);
-  println!("{:?}", 1i8 as u64);
-  println!("{:?}", 1i8 as f32);
-  println!("{:?}", 1i8 as f64);
-
-  println!("{:?}", 1u8 as isize);
-  println!("{:?}", 1u8 as usize);
-  println!("{:?}", 1u8 as *const String);
-  println!("{:?}", 1u8 as i8);
-  println!("{:?}", 1u8 as i16);
-  println!("{:?}", 1u8 as i32);
-  println!("{:?}", 1u8 as i64);
-  println!("{:?}", 1u8 as u8);
-  println!("{:?}", 1u8 as u16);
-  println!("{:?}", 1u8 as u32);
-  println!("{:?}", 1u8 as u64);
-  println!("{:?}", 1u8 as f32);
-  println!("{:?}", 1u8 as f64);
-
-  println!("{:?}", 1i16 as isize);
-  println!("{:?}", 1i16 as usize);
-  println!("{:?}", 1i16 as *const String);
-  println!("{:?}", 1i16 as i8);
-  println!("{:?}", 1i16 as i16);
-  println!("{:?}", 1i16 as i32);
-  println!("{:?}", 1i16 as i64);
-  println!("{:?}", 1i16 as u8);
-  println!("{:?}", 1i16 as u16);
-  println!("{:?}", 1i16 as u32);
-  println!("{:?}", 1i16 as u64);
-  println!("{:?}", 1i16 as f32);
-  println!("{:?}", 1i16 as f64);
-
-  println!("{:?}", 1u16 as isize);
-  println!("{:?}", 1u16 as usize);
-  println!("{:?}", 1u16 as *const String);
-  println!("{:?}", 1u16 as i8);
-  println!("{:?}", 1u16 as i16);
-  println!("{:?}", 1u16 as i32);
-  println!("{:?}", 1u16 as i64);
-  println!("{:?}", 1u16 as u8);
-  println!("{:?}", 1u16 as u16);
-  println!("{:?}", 1u16 as u32);
-  println!("{:?}", 1u16 as u64);
-  println!("{:?}", 1u16 as f32);
-  println!("{:?}", 1u16 as f64);
-
-  println!("{:?}", 1i32 as isize);
-  println!("{:?}", 1i32 as usize);
-  println!("{:?}", 1i32 as *const String);
-  println!("{:?}", 1i32 as i8);
-  println!("{:?}", 1i32 as i16);
-  println!("{:?}", 1i32 as i32);
-  println!("{:?}", 1i32 as i64);
-  println!("{:?}", 1i32 as u8);
-  println!("{:?}", 1i32 as u16);
-  println!("{:?}", 1i32 as u32);
-  println!("{:?}", 1i32 as u64);
-  println!("{:?}", 1i32 as f32);
-  println!("{:?}", 1i32 as f64);
-
-  println!("{:?}", 1u32 as isize);
-  println!("{:?}", 1u32 as usize);
-  println!("{:?}", 1u32 as *const String);
-  println!("{:?}", 1u32 as i8);
-  println!("{:?}", 1u32 as i16);
-  println!("{:?}", 1u32 as i32);
-  println!("{:?}", 1u32 as i64);
-  println!("{:?}", 1u32 as u8);
-  println!("{:?}", 1u32 as u16);
-  println!("{:?}", 1u32 as u32);
-  println!("{:?}", 1u32 as u64);
-  println!("{:?}", 1u32 as f32);
-  println!("{:?}", 1u32 as f64);
-
-  println!("{:?}", 1i64 as isize);
-  println!("{:?}", 1i64 as usize);
-  println!("{:?}", 1i64 as *const String);
-  println!("{:?}", 1i64 as i8);
-  println!("{:?}", 1i64 as i16);
-  println!("{:?}", 1i64 as i32);
-  println!("{:?}", 1i64 as i64);
-  println!("{:?}", 1i64 as u8);
-  println!("{:?}", 1i64 as u16);
-  println!("{:?}", 1i64 as u32);
-  println!("{:?}", 1i64 as u64);
-  println!("{:?}", 1i64 as f32);
-  println!("{:?}", 1i64 as f64);
-
-  println!("{:?}", 1u64 as isize);
-  println!("{:?}", 1u64 as usize);
-  println!("{:?}", 1u64 as *const String);
-  println!("{:?}", 1u64 as i8);
-  println!("{:?}", 1u64 as i16);
-  println!("{:?}", 1u64 as i32);
-  println!("{:?}", 1u64 as i64);
-  println!("{:?}", 1u64 as u8);
-  println!("{:?}", 1u64 as u16);
-  println!("{:?}", 1u64 as u32);
-  println!("{:?}", 1u64 as u64);
-  println!("{:?}", 1u64 as f32);
-  println!("{:?}", 1u64 as f64);
-
-  println!("{:?}", 1u64 as isize);
-  println!("{:?}", 1u64 as usize);
-  println!("{:?}", 1u64 as *const String);
-  println!("{:?}", 1u64 as i8);
-  println!("{:?}", 1u64 as i16);
-  println!("{:?}", 1u64 as i32);
-  println!("{:?}", 1u64 as i64);
-  println!("{:?}", 1u64 as u8);
-  println!("{:?}", 1u64 as u16);
-  println!("{:?}", 1u64 as u32);
-  println!("{:?}", 1u64 as u64);
-  println!("{:?}", 1u64 as f32);
-  println!("{:?}", 1u64 as f64);
-
-  println!("{:?}", true as isize);
-  println!("{:?}", true as usize);
-  println!("{:?}", true as i8);
-  println!("{:?}", true as i16);
-  println!("{:?}", true as i32);
-  println!("{:?}", true as i64);
-  println!("{:?}", true as u8);
-  println!("{:?}", true as u16);
-  println!("{:?}", true as u32);
-  println!("{:?}", true as u64);
-
-  println!("{:?}", 1f32 as isize);
-  println!("{:?}", 1f32 as usize);
-  println!("{:?}", 1f32 as i8);
-  println!("{:?}", 1f32 as i16);
-  println!("{:?}", 1f32 as i32);
-  println!("{:?}", 1f32 as i64);
-  println!("{:?}", 1f32 as u8);
-  println!("{:?}", 1f32 as u16);
-  println!("{:?}", 1f32 as u32);
-  println!("{:?}", 1f32 as u64);
-  println!("{:?}", 1f32 as f32);
-  println!("{:?}", 1f32 as f64);
-
-  println!("{:?}", 1f64 as isize);
-  println!("{:?}", 1f64 as usize);
-  println!("{:?}", 1f64 as i8);
-  println!("{:?}", 1f64 as i16);
-  println!("{:?}", 1f64 as i32);
-  println!("{:?}", 1f64 as i64);
-  println!("{:?}", 1f64 as u8);
-  println!("{:?}", 1f64 as u16);
-  println!("{:?}", 1f64 as u32);
-  println!("{:?}", 1f64 as u64);
-  println!("{:?}", 1f64 as f32);
-  println!("{:?}", 1f64 as f64);
-}
diff --git a/src/test/ui/svh/auxiliary/changing-crates-a1.rs b/src/test/ui/svh/auxiliary/changing-crates-a1.rs
new file mode 100644 (file)
index 0000000..bc0559b
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_name = "a"]
+
+pub fn foo<T>() {}
diff --git a/src/test/ui/svh/auxiliary/changing-crates-a2.rs b/src/test/ui/svh/auxiliary/changing-crates-a2.rs
new file mode 100644 (file)
index 0000000..fafc6d5
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_name = "a"]
+
+pub fn foo<T>() { println!("hello!"); }
diff --git a/src/test/ui/svh/auxiliary/changing-crates-b.rs b/src/test/ui/svh/auxiliary/changing-crates-b.rs
new file mode 100644 (file)
index 0000000..f9ce29e
--- /dev/null
@@ -0,0 +1,5 @@
+#![crate_name = "b"]
+
+extern crate a;
+
+pub fn foo() { a::foo::<isize>(); }
diff --git a/src/test/ui/svh/changing-crates.rs b/src/test/ui/svh/changing-crates.rs
new file mode 100644 (file)
index 0000000..60c043b
--- /dev/null
@@ -0,0 +1,12 @@
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:changing-crates-a1.rs
+// aux-build:changing-crates-b.rs
+// aux-build:changing-crates-a2.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {}
diff --git a/src/test/ui/svh/changing-crates.stderr b/src/test/ui/svh/changing-crates.stderr
new file mode 100644 (file)
index 0000000..cc62a4d
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+  --> $DIR/changing-crates.rs:10:1
+   |
+LL | extern crate b;
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: perhaps that crate needs to be recompiled?
+   = note: the following crate versions were found:
+           crate `a`: $PATH_a
+           crate `b`: $PATH_b
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/syntax-trait-polarity.rs b/src/test/ui/syntax-trait-polarity.rs
deleted file mode 100644 (file)
index ed29474..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#![feature(negative_impls)]
-
-use std::marker::Send;
-
-struct TestType;
-
-impl !TestType {}
-//~^ ERROR inherent impls cannot be negative
-
-trait TestTrait {}
-
-unsafe impl !Send for TestType {}
-//~^ ERROR negative impls cannot be unsafe
-impl !TestTrait for TestType {}
-
-struct TestType2<T>(T);
-
-impl<T> !TestType2<T> {}
-//~^ ERROR inherent impls cannot be negative
-
-unsafe impl<T> !Send for TestType2<T> {}
-//~^ ERROR negative impls cannot be unsafe
-impl<T> !TestTrait for TestType2<T> {}
-
-fn main() {}
diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr
deleted file mode 100644 (file)
index 1fd40fb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:7:7
-   |
-LL | impl !TestType {}
-   |      -^^^^^^^^ inherent impl for this type
-   |      |
-   |      negative because of this
-
-error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:12:13
-   |
-LL | unsafe impl !Send for TestType {}
-   | ------      -^^^^
-   | |           |
-   | |           negative because of this
-   | unsafe because of this
-
-error: inherent impls cannot be negative
-  --> $DIR/syntax-trait-polarity.rs:18:10
-   |
-LL | impl<T> !TestType2<T> {}
-   |         -^^^^^^^^^^^^ inherent impl for this type
-   |         |
-   |         negative because of this
-
-error[E0198]: negative impls cannot be unsafe
-  --> $DIR/syntax-trait-polarity.rs:21:16
-   |
-LL | unsafe impl<T> !Send for TestType2<T> {}
-   | ------         -^^^^
-   | |              |
-   | |              negative because of this
-   | unsafe because of this
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0198`.
index 101132d05fa0eb98f6a5d0f05e45d20800f5a2b4..5cb9ad31fbfcc0a2ac95366084206839702fa26d 100644 (file)
@@ -3,18 +3,27 @@ error[E0632]: cannot provide explicit generic arguments when `impl Trait` is use
    |
 LL |     func::<u8>(42);
    |            ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
   --> $DIR/synthetic-param.rs:23:17
    |
 LL |     Foo::func::<u8>(42);
    |                 ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
   --> $DIR/synthetic-param.rs:26:23
    |
 LL |     Bar::<i8>::func::<u8>(42);
    |                       ^^ explicit generic argument not allowed
+   |
+   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
+   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/terminate-in-initializer.rs b/src/test/ui/terminate-in-initializer.rs
deleted file mode 100644 (file)
index c9cb932..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-
-// Issue #787
-// Don't try to clean up uninitialized locals
-
-
-use std::thread;
-
-fn test_break() { loop { let _x: Box<isize> = break; } }
-
-fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box<isize> = continue; } }
-
-fn test_ret() { let _x: Box<isize> = return; }
-
-fn test_panic() {
-    fn f() { let _x: Box<isize> = panic!(); }
-    thread::spawn(move|| f() ).join().unwrap_err();
-}
-
-fn test_panic_indirect() {
-    fn f() -> ! { panic!(); }
-    fn g() { let _x: Box<isize> = f(); }
-    thread::spawn(move|| g() ).join().unwrap_err();
-}
-
-pub fn main() {
-    test_break();
-    test_cont();
-    test_ret();
-    test_panic();
-    test_panic_indirect();
-}
index 869b372965966ffaebb6b17d83db3dbed5cb2e13..65d90678040d5ff094278cde42b3bb483ad2d067 100644 (file)
@@ -6,6 +6,10 @@ LL |     want_foo(b);
    |
    = note: expected struct `Foo`
               found struct `Box<Foo>`
+help: try dereferencing the `Box`
+   |
+LL |     want_foo(*b);
+   |              +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/test-attrs/issue-20823.rs b/src/test/ui/test-attrs/issue-20823.rs
new file mode 100644 (file)
index 0000000..9e209d5
--- /dev/null
@@ -0,0 +1,5 @@
+// run-pass
+// compile-flags: --test
+
+#[test]
+pub fn foo() {}
diff --git a/src/test/ui/thin-lto-global-allocator.rs b/src/test/ui/thin-lto-global-allocator.rs
deleted file mode 100644 (file)
index e00c5ca..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-// compile-flags: -Z thinlto -C codegen-units=2
-
-#[global_allocator]
-static A: std::alloc::System = std::alloc::System;
-
-fn main() {}
diff --git a/src/test/ui/thinlto/all-crates.rs b/src/test/ui/thinlto/all-crates.rs
deleted file mode 100644 (file)
index e910b2a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-// compile-flags: -Clto=thin
-// no-prefer-dynamic
-
-fn main() {
-    println!("hello!");
-}
diff --git a/src/test/ui/thinlto/auxiliary/dylib.rs b/src/test/ui/thinlto/auxiliary/dylib.rs
deleted file mode 100644 (file)
index e8b7f8f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// compile-flags: -Z thinlto -C codegen-units=8
-
-#[inline]
-pub fn foo(b: u8) {
-    b.to_string();
-}
diff --git a/src/test/ui/thinlto/auxiliary/msvc-imp-present.rs b/src/test/ui/thinlto/auxiliary/msvc-imp-present.rs
deleted file mode 100644 (file)
index 933af05..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// no-prefer-dynamic
-// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic
-
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
-
-pub static A: u32 = 43;
-
-pub mod a {
-    pub static A: u32 = 43;
-}
diff --git a/src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs b/src/test/ui/thinlto/auxiliary/thin-lto-inlines-aux.rs
deleted file mode 100644 (file)
index 5fd3f19..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn bar() -> u32 {
-    3
-}
diff --git a/src/test/ui/thinlto/dylib-works.rs b/src/test/ui/thinlto/dylib-works.rs
deleted file mode 100644 (file)
index 9e0782b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-
-// aux-build:dylib.rs
-
-extern crate dylib;
-
-fn main() {
-    dylib::foo(1);
-}
diff --git a/src/test/ui/thinlto/msvc-imp-present.rs b/src/test/ui/thinlto/msvc-imp-present.rs
deleted file mode 100644 (file)
index 5498afb..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-
-// aux-build:msvc-imp-present.rs
-// compile-flags: -Z thinlto -C codegen-units=8
-// no-prefer-dynamic
-
-// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name`
-// for all exported statics. This is done because we apply `dllimport` to all
-// imported constants and this allows everything to actually link correctly.
-//
-// The ThinLTO passes aggressively remove symbols if they can, and this test
-// asserts that the ThinLTO passes don't remove these compiler-generated
-// `_imp_*` symbols. The external library that we link in here is compiled with
-// ThinLTO and multiple codegen units and has a few exported constants. Note
-// that we also namely compile the library as both a dylib and an rlib, but we
-// link the rlib to ensure that we assert those generated symbols exist.
-
-extern crate msvc_imp_present as bar;
-
-fn main() {
-    println!("{}", bar::A);
-}
diff --git a/src/test/ui/thinlto/thin-lto-inlines.rs b/src/test/ui/thinlto/thin-lto-inlines.rs
deleted file mode 100644 (file)
index dca7918..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-
-// compile-flags: -Z thinlto -C codegen-units=8 -O
-// ignore-emscripten can't inspect instructions on emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-pub fn foo() -> u32 {
-    bar::bar()
-}
-
-mod bar {
-    pub fn bar() -> u32 {
-        3
-    }
-}
-
-fn main() {
-    println!("{} {}", foo(), bar::bar());
-
-    unsafe {
-        let foo = foo as usize as *const u8;
-        let bar = bar::bar as usize as *const u8;
-
-        assert_eq!(*foo, *bar);
-    }
-}
diff --git a/src/test/ui/thinlto/thin-lto-inlines2.rs b/src/test/ui/thinlto/thin-lto-inlines2.rs
deleted file mode 100644 (file)
index 1eb2965..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// run-pass
-
-// compile-flags: -C codegen-units=8 -O -C lto=thin
-// aux-build:thin-lto-inlines-aux.rs
-// no-prefer-dynamic
-// ignore-emscripten can't inspect instructions on emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-extern crate thin_lto_inlines_aux as bar;
-
-pub fn foo() -> u32 {
-    bar::bar()
-}
-
-fn main() {
-    println!("{} {}", foo(), bar::bar());
-
-    unsafe {
-        let foo = foo as usize as *const u8;
-        let bar = bar::bar as usize as *const u8;
-
-        assert_eq!(*foo, *bar);
-    }
-}
diff --git a/src/test/ui/thinlto/weak-works.rs b/src/test/ui/thinlto/weak-works.rs
deleted file mode 100644 (file)
index 163a387..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// run-pass
-
-// compile-flags: -C codegen-units=8 -Z thinlto
-// ignore-windows
-
-#![feature(linkage)]
-
-pub mod foo {
-    #[linkage = "weak"]
-    #[no_mangle]
-    pub extern "C" fn FOO() -> i32 {
-        0
-    }
-}
-
-mod bar {
-    extern "C" {
-        fn FOO() -> i32;
-    }
-
-    pub fn bar() -> i32 {
-        unsafe { FOO() }
-    }
-}
-
-fn main() {
-    bar::bar();
-}
diff --git a/src/test/ui/threads-sendsync/issue-24313.rs b/src/test/ui/threads-sendsync/issue-24313.rs
new file mode 100644 (file)
index 0000000..c28b4ca
--- /dev/null
@@ -0,0 +1,32 @@
+// run-pass
+// ignore-emscripten no threads
+// ignore-sgx no processes
+
+use std::thread;
+use std::env;
+use std::process::Command;
+
+struct Handle(i32);
+
+impl Drop for Handle {
+    fn drop(&mut self) { panic!(); }
+}
+
+thread_local!(static HANDLE: Handle = Handle(0));
+
+fn main() {
+    let args = env::args().collect::<Vec<_>>();
+    if args.len() == 1 {
+        let out = Command::new(&args[0]).arg("test").output().unwrap();
+        let stderr = std::str::from_utf8(&out.stderr).unwrap();
+        assert!(stderr.contains("panicked at 'explicit panic'"),
+                "bad failure message:\n{}\n", stderr);
+    } else {
+        // TLS dtors are not always run on process exit
+        thread::spawn(|| {
+            HANDLE.with(|h| {
+                println!("{}", h.0);
+            });
+        }).join().unwrap();
+    }
+}
diff --git a/src/test/ui/threads-sendsync/issue-4448.rs b/src/test/ui/threads-sendsync/issue-4448.rs
new file mode 100644 (file)
index 0000000..27d0326
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+// ignore-emscripten no threads support
+
+use std::sync::mpsc::channel;
+use std::thread;
+
+pub fn main() {
+    let (tx, rx) = channel::<&'static str>();
+
+    let t = thread::spawn(move|| {
+        assert_eq!(rx.recv().unwrap(), "hello, world");
+    });
+
+    tx.send("hello, world").unwrap();
+    t.join().ok().unwrap();
+}
diff --git a/src/test/ui/threads-sendsync/issue-8827.rs b/src/test/ui/threads-sendsync/issue-8827.rs
new file mode 100644 (file)
index 0000000..95be761
--- /dev/null
@@ -0,0 +1,53 @@
+// run-pass
+// ignore-emscripten no threads support
+
+use std::thread;
+use std::sync::mpsc::{channel, Receiver};
+
+fn periodical(n: isize) -> Receiver<bool> {
+    let (chan, port) = channel();
+    thread::spawn(move|| {
+        loop {
+            for _ in 1..n {
+                match chan.send(false) {
+                    Ok(()) => {}
+                    Err(..) => break,
+                }
+            }
+            match chan.send(true) {
+                Ok(()) => {}
+                Err(..) => break
+            }
+        }
+    });
+    return port;
+}
+
+fn integers() -> Receiver<isize> {
+    let (chan, port) = channel();
+    thread::spawn(move|| {
+        let mut i = 1;
+        loop {
+            match chan.send(i) {
+                Ok(()) => {}
+                Err(..) => break,
+            }
+            i = i + 1;
+        }
+    });
+    return port;
+}
+
+fn main() {
+    let ints = integers();
+    let threes = periodical(3);
+    let fives = periodical(5);
+    for _ in 1..100 {
+        match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) {
+            (_, true, true) => println!("FizzBuzz"),
+            (_, true, false) => println!("Fizz"),
+            (_, false, true) => println!("Buzz"),
+            (i, false, false) => println!("{}", i)
+        }
+    }
+}
diff --git a/src/test/ui/threads-sendsync/issue-9396.rs b/src/test/ui/threads-sendsync/issue-9396.rs
new file mode 100644 (file)
index 0000000..3e7e9a5
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+#![allow(unused_must_use)]
+#![allow(deprecated)]
+// ignore-emscripten no threads support
+
+use std::sync::mpsc::{TryRecvError, channel};
+use std::thread;
+
+pub fn main() {
+    let (tx, rx) = channel();
+    let t = thread::spawn(move||{
+        thread::sleep_ms(10);
+        tx.send(()).unwrap();
+    });
+    loop {
+        match rx.try_recv() {
+            Ok(()) => break,
+            Err(TryRecvError::Empty) => {}
+            Err(TryRecvError::Disconnected) => unreachable!()
+        }
+    }
+    t.join();
+}
diff --git a/src/test/ui/threads-sendsync/trivial-message.rs b/src/test/ui/threads-sendsync/trivial-message.rs
new file mode 100644 (file)
index 0000000..5831e86
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+
+#![allow(unused_must_use)]
+/*
+  This is about the simplest program that can successfully send a
+  message.
+ */
+
+use std::sync::mpsc::channel;
+
+pub fn main() {
+    let (tx, rx) = channel();
+    tx.send(42);
+    let r = rx.recv();
+    println!("{:?}", r);
+}
diff --git a/src/test/ui/threads-sendsync/yield2.rs b/src/test/ui/threads-sendsync/yield2.rs
new file mode 100644 (file)
index 0000000..376faab
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+
+use std::thread;
+
+pub fn main() {
+    let mut i: isize = 0;
+    while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); }
+}
diff --git a/src/test/ui/trace_macros-format.rs b/src/test/ui/trace_macros-format.rs
deleted file mode 100644 (file)
index afca45c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#![feature(trace_macros)]
-
-fn main() {
-    trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
-    trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
-
-
-    // should be fine:
-    macro_rules! expando {
-        ($x: ident) => { trace_macros!($x) }
-    }
-
-    expando!(true);
-}
diff --git a/src/test/ui/trace_macros-format.stderr b/src/test/ui/trace_macros-format.stderr
deleted file mode 100644 (file)
index c320270..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:4:5
-   |
-LL |     trace_macros!();
-   |     ^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:5:5
-   |
-LL |     trace_macros!(1);
-   |     ^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:6:5
-   |
-LL |     trace_macros!(ident);
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:7:5
-   |
-LL |     trace_macros!(for);
-   |     ^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:8:5
-   |
-LL |     trace_macros!(true,);
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
-  --> $DIR/trace_macros-format.rs:9:5
-   |
-LL |     trace_macros!(false 1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 6 previous errors
-
index 0ab39ae66728817fe79532d06078e3c82ecaed18..6a3498a389375e3806243cde691d6ae85f3064c0 100644 (file)
@@ -1,11 +1,3 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
-  --> $DIR/issue-83613.rs:10:1
-   |
-LL | impl<T: Send> AnotherTrait for T {}
-   | -------------------------------- first implementation here
-LL | impl AnotherTrait for OpaqueType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait`
-
 error: cannot implement trait on type alias impl trait
   --> $DIR/issue-83613.rs:10:1
    |
@@ -18,6 +10,14 @@ note: type alias impl trait defined here
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
 
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `impl OpaqueTrait`
+  --> $DIR/issue-83613.rs:10:1
+   |
+LL | impl<T: Send> AnotherTrait for T {}
+   | -------------------------------- first implementation here
+LL | impl AnotherTrait for OpaqueType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `impl OpaqueTrait`
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/traits/issue-24010.rs b/src/test/ui/traits/issue-24010.rs
new file mode 100644 (file)
index 0000000..f181853
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+
+trait Foo: Fn(i32) -> i32 + Send {}
+
+impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
+
+fn wants_foo(f: Box<dyn Foo>) -> i32 {
+    f(42)
+}
+
+fn main() {
+    let f = Box::new(|x| x);
+    assert_eq!(wants_foo(f), 42);
+}
diff --git a/src/test/ui/traits/issue-38604.rs b/src/test/ui/traits/issue-38604.rs
new file mode 100644 (file)
index 0000000..002a3c4
--- /dev/null
@@ -0,0 +1,16 @@
+trait Q<T:?Sized> {}
+trait Foo where u32: Q<Self> {
+    fn foo(&self);
+}
+
+impl Q<()> for u32 {}
+impl Foo for () {
+    fn foo(&self) {
+        println!("foo!");
+    }
+}
+
+fn main() {
+    let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
+        Box::new(()); //~ ERROR `Foo` cannot be made into an object
+}
diff --git a/src/test/ui/traits/issue-38604.stderr b/src/test/ui/traits/issue-38604.stderr
new file mode 100644 (file)
index 0000000..d41488c
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/issue-38604.rs:14:13
+   |
+LL |     let _f: Box<dyn Foo> =
+   |             ^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-38604.rs:2:22
+   |
+LL | trait Foo where u32: Q<Self> {
+   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/issue-38604.rs:15:9
+   |
+LL |         Box::new(());
+   |         ^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-38604.rs:2:22
+   |
+LL | trait Foo where u32: Q<Self> {
+   |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<()>`
+   = note: required by cast to type `Box<dyn Foo>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/issue-3973.rs b/src/test/ui/traits/issue-3973.rs
new file mode 100644 (file)
index 0000000..a5ed5b8
--- /dev/null
@@ -0,0 +1,25 @@
+struct Point {
+    x: f64,
+    y: f64,
+}
+
+trait ToString_ {
+    fn to_string(&self) -> String;
+}
+
+impl ToString_ for Point {
+    fn new(x: f64, y: f64) -> Point {
+    //~^ ERROR method `new` is not a member of trait `ToString_`
+        Point { x: x, y: y }
+    }
+
+    fn to_string(&self) -> String {
+        format!("({}, {})", self.x, self.y)
+    }
+}
+
+fn main() {
+    let p = Point::new(0.0, 0.0);
+    //~^ ERROR no function or associated item named `new` found for struct `Point`
+    println!("{}", p.to_string());
+}
diff --git a/src/test/ui/traits/issue-3973.stderr b/src/test/ui/traits/issue-3973.stderr
new file mode 100644 (file)
index 0000000..63282e8
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0407]: method `new` is not a member of trait `ToString_`
+  --> $DIR/issue-3973.rs:11:5
+   |
+LL | /     fn new(x: f64, y: f64) -> Point {
+LL | |
+LL | |         Point { x: x, y: y }
+LL | |     }
+   | |_____^ not a member of trait `ToString_`
+
+error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
+  --> $DIR/issue-3973.rs:22:20
+   |
+LL | struct Point {
+   | ------------ function or associated item `new` not found for this
+...
+LL |     let p = Point::new(0.0, 0.0);
+   |                    ^^^ function or associated item not found in `Point`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0407, E0599.
+For more information about an error, try `rustc --explain E0407`.
diff --git a/src/test/ui/traits/issue-59029-1.rs b/src/test/ui/traits/issue-59029-1.rs
new file mode 100644 (file)
index 0000000..8ab47a4
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+//~^ ERROR associated type `Res` not found for `Self`
+//~| ERROR associated type `Res` not found for `Self`
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-59029-1.stderr b/src/test/ui/traits/issue-59029-1.stderr
new file mode 100644 (file)
index 0000000..53cdb8b
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:52
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                                    ^^^ associated type `Res` not found
+
+error[E0220]: associated type `Res` not found for `Self`
+  --> $DIR/issue-59029-1.rs:5:52
+   |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+   |                                                    ^^^ associated type `Res` not found
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/src/test/ui/traits/issue-72455.rs b/src/test/ui/traits/issue-72455.rs
new file mode 100644 (file)
index 0000000..b6c3bb2
--- /dev/null
@@ -0,0 +1,27 @@
+// check-pass
+
+pub trait ResultExt {
+    type Ok;
+    fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
+}
+
+impl<O, E> ResultExt for std::result::Result<O, E>
+where
+    E: std::error::Error,
+{
+    type Ok = O;
+    fn err_eprint_and_ignore(self) -> Option<O>
+    where
+        Self: ,
+    {
+        match self {
+            Err(e) => {
+                eprintln!("{}", e);
+                None
+            }
+            Ok(o) => Some(o),
+        }
+    }
+}
+
+fn main() {}
index 0150ff41303ae3439416b48a563c4c04298c5403..49a9f479368769d4186a87fc61038fd331bf048e 100644 (file)
@@ -50,12 +50,6 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
    |
    = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
 
-error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
-  --> $DIR/issue-78372.rs:3:1
-   |
-LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`)
   --> $DIR/issue-78372.rs:3:6
    |
@@ -65,6 +59,12 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
    = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
    = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
+  --> $DIR/issue-78372.rs:3:1
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0210, E0378, E0412, E0658.
diff --git a/src/test/ui/traits/object-does-not-impl-trait.rs b/src/test/ui/traits/object-does-not-impl-trait.rs
new file mode 100644 (file)
index 0000000..b3b6798
--- /dev/null
@@ -0,0 +1,8 @@
+// Test that an object type `Box<Foo>` is not considered to implement the
+// trait `Foo`. Issue #5087.
+
+trait Foo {}
+fn take_foo<F:Foo>(f: F) {}
+fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied
+fn main() {}
diff --git a/src/test/ui/traits/object-does-not-impl-trait.stderr b/src/test/ui/traits/object-does-not-impl-trait.stderr
new file mode 100644 (file)
index 0000000..f1dd508
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
+  --> $DIR/object-does-not-impl-trait.rs:6:44
+   |
+LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+   |                                   -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+   |                                   |
+   |                                   required by a bound introduced by this call
+   |
+note: required by a bound in `take_foo`
+  --> $DIR/object-does-not-impl-trait.rs:5:15
+   |
+LL | fn take_foo<F:Foo>(f: F) {}
+   |               ^^^ required by this bound in `take_foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/traits/syntax-trait-polarity.rs b/src/test/ui/traits/syntax-trait-polarity.rs
new file mode 100644 (file)
index 0000000..ed29474
--- /dev/null
@@ -0,0 +1,25 @@
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent impls cannot be negative
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
+impl !TestTrait for TestType {}
+
+struct TestType2<T>(T);
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent impls cannot be negative
+
+unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
diff --git a/src/test/ui/traits/syntax-trait-polarity.stderr b/src/test/ui/traits/syntax-trait-polarity.stderr
new file mode 100644 (file)
index 0000000..1fd40fb
--- /dev/null
@@ -0,0 +1,37 @@
+error: inherent impls cannot be negative
+  --> $DIR/syntax-trait-polarity.rs:7:7
+   |
+LL | impl !TestType {}
+   |      -^^^^^^^^ inherent impl for this type
+   |      |
+   |      negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/syntax-trait-polarity.rs:12:13
+   |
+LL | unsafe impl !Send for TestType {}
+   | ------      -^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+error: inherent impls cannot be negative
+  --> $DIR/syntax-trait-polarity.rs:18:10
+   |
+LL | impl<T> !TestType2<T> {}
+   |         -^^^^^^^^^^^^ inherent impl for this type
+   |         |
+   |         negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/syntax-trait-polarity.rs:21:16
+   |
+LL | unsafe impl<T> !Send for TestType2<T> {}
+   | ------         -^^^^
+   | |              |
+   | |              negative because of this
+   | unsafe because of this
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0198`.
diff --git a/src/test/ui/transmute-specialization.rs b/src/test/ui/transmute-specialization.rs
deleted file mode 100644 (file)
index 499334d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-trait Specializable { type Output; }
-
-impl<T> Specializable for T {
-    default type Output = u16;
-}
-
-fn main() {
-    unsafe {
-        std::mem::transmute::<u16, <() as Specializable>::Output>(0);
-    }
-}
diff --git a/src/test/ui/transmute-specialization.stderr b/src/test/ui/transmute-specialization.stderr
deleted file mode 100644 (file)
index a0ea724..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/transmute-specialization.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/trivial-message.rs b/src/test/ui/trivial-message.rs
deleted file mode 100644 (file)
index 5831e86..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-pass
-
-#![allow(unused_must_use)]
-/*
-  This is about the simplest program that can successfully send a
-  message.
- */
-
-use std::sync::mpsc::channel;
-
-pub fn main() {
-    let (tx, rx) = channel();
-    tx.send(42);
-    let r = rx.recv();
-    println!("{:?}", r);
-}
diff --git a/src/test/ui/try-block/issue-45124.rs b/src/test/ui/try-block/issue-45124.rs
new file mode 100644 (file)
index 0000000..942014c
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(unreachable_code)]
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+    let mut a = 0;
+    let () = {
+        let _: Result<(), ()> = try {
+            let _ = Err(())?;
+            return
+        };
+        a += 1;
+    };
+    a += 2;
+    assert_eq!(a, 3);
+}
diff --git a/src/test/ui/try-macro-suggestion.rs b/src/test/ui/try-macro-suggestion.rs
deleted file mode 100644 (file)
index 635ceac..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags: --edition 2018
-fn foo() -> Result<(), ()> {
-    Ok(try!()); //~ ERROR use of deprecated `try` macro
-    Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
-}
-
-fn main() {
-    let _ = foo();
-}
diff --git a/src/test/ui/try-macro-suggestion.stderr b/src/test/ui/try-macro-suggestion.stderr
deleted file mode 100644 (file)
index c7dde7e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-error: use of deprecated `try` macro
-  --> $DIR/try-macro-suggestion.rs:3:8
-   |
-LL |     Ok(try!());
-   |        ^^^^^^
-   |
-   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
-help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax
-   |
-LL |     Ok(r#try!());
-   |        ++
-
-error: use of deprecated `try` macro
-  --> $DIR/try-macro-suggestion.rs:4:8
-   |
-LL |     Ok(try!(Ok(())))
-   |        ^^^^^^^^^^^^
-   |
-   = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
-help: you can use the `?` operator instead
-   |
-LL -     Ok(try!(Ok(())))
-LL +     Ok(Ok(())?)
-   | 
-help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax
-   |
-LL |     Ok(r#try!(Ok(())))
-   |        ++
-
-error: aborting due to 2 previous errors
-
index 5f3b711b31aa91bac473564d7e63ac574a05d3b5..acbf15dcb6c6a937d5f49b0e3948b0b470bbb587 100644 (file)
@@ -31,7 +31,10 @@ impl Tr for E {
     type V = u8;
     fn f() -> Self::V { 0 }
     //~^ ERROR ambiguous associated item
+    //~| ERROR ambiguous associated item
     //~| WARN this was previously accepted
+    //~| WARN this was previously accepted
+    //~| HELP use fully-qualified syntax
     //~| HELP use fully-qualified syntax
 }
 
index 870b1eec48c0c8a476f386153d72d6264319f10f..f007f71a73c4532323fdaf2324211e1f290d9c9b 100644 (file)
@@ -18,5 +18,24 @@ note: `V` could also refer to the associated type defined here
 LL |     type V;
    |     ^^^^^^^
 
-error: aborting due to previous error
+error: ambiguous associated item
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15
+   |
+LL |     fn f() -> Self::V { 0 }
+   |               ^^^^^^^ help: use fully-qualified syntax: `<E as Tr>::V`
+   |
+   = 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 #57644 <https://github.com/rust-lang/rust/issues/57644>
+note: `V` could refer to the variant defined here
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5
+   |
+LL |     V
+   |     ^
+note: `V` could also refer to the associated type defined here
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5
+   |
+LL |     type V;
+   |     ^^^^^^^
+
+error: aborting due to 2 previous errors
 
index c46c4715924e59439ba11f562da9504b1d4e606f..685d76ee36f33cb5f3a56a48dde128810e019540 100644 (file)
@@ -8,8 +8,7 @@ trait MyTrait {}
 impl MyTrait for () {}
 
 impl<F> FnOnce<()> for &F {
-    //~^ ERROR conflicting implementations
-    //~| ERROR type parameter `F` must be used
+    //~^ ERROR type parameter `F` must be used
     type Output = impl MyTrait;
     extern "rust-call" fn call_once(self, _: ()) -> Self::Output {}
 }
index e1e259187f5f9d60dcf06708993001c6cccad442..b93ea955c89f59303965a5b86d7b4a60d8072894 100644 (file)
@@ -1,13 +1,3 @@
-error[E0119]: conflicting implementations of trait `std::ops::FnOnce<()>` for type `&_`
-  --> $DIR/incoherent-assoc-imp-trait.rs:10:1
-   |
-LL | impl<F> FnOnce<()> for &F {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: conflicting implementation in crate `core`:
-           - impl<A, F> FnOnce<A> for &F
-             where F: Fn<A>, F: ?Sized;
-
 error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct<F>`)
   --> $DIR/incoherent-assoc-imp-trait.rs:10:6
    |
@@ -17,7 +7,6 @@ LL | impl<F> FnOnce<()> for &F {
    = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0119, E0210.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-60662.rs b/src/test/ui/type-alias-impl-trait/issue-60662.rs
new file mode 100644 (file)
index 0000000..b9faa66
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+// compile-flags: -Z unpretty=hir
+
+#![feature(type_alias_impl_trait)]
+
+trait Animal {}
+
+fn main() {
+    pub type ServeFut = impl Animal;
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-60662.stdout b/src/test/ui/type-alias-impl-trait/issue-60662.stdout
new file mode 100644 (file)
index 0000000..14a49f2
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+// compile-flags: -Z unpretty=hir
+
+#![feature(type_alias_impl_trait)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+trait Animal { }
+
+fn main() {
+              pub type ServeFut = /*impl Trait*/;
+          }
diff --git a/src/test/ui/type-inference/issue-30225.rs b/src/test/ui/type-inference/issue-30225.rs
new file mode 100644 (file)
index 0000000..4231533
--- /dev/null
@@ -0,0 +1,38 @@
+// Regression test for #30225, which was an ICE that would trigger as
+// a result of a poor interaction between trait result caching and
+// type inference. Specifically, at that time, unification could cause
+// unrelated type variables to become instantiated, if subtyping
+// relationships existed. These relationships are now propagated
+// through obligations and hence everything works out fine.
+
+trait Foo<U,V> : Sized {
+    fn foo(self, u: Option<U>, v: Option<V>) {}
+}
+
+struct A;
+struct B;
+
+impl Foo<A, B> for () {}      // impl A
+impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
+
+fn toxic() {
+    // cache the resolution <() as Foo<$0,$1>> = impl A
+    let u = None;
+    let v = None;
+    Foo::foo((), u, v);
+}
+
+fn bomb() {
+    let mut u = None; // type is Option<$0>
+    let mut v = None; // type is Option<$1>
+    let mut x = None; // type is Option<$2>
+
+    Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
+    u = v; // mark $0 and $1 in a subtype relationship
+    //~^ ERROR mismatched types
+    x = Some(()); // set $2 = (), allowing impl selection
+                  // to proceed for <() as Foo<$0, $1>> = impl A.
+                  // kaboom, this *used* to trigge an ICE
+}
+
+fn main() {}
diff --git a/src/test/ui/type-inference/issue-30225.stderr b/src/test/ui/type-inference/issue-30225.stderr
new file mode 100644 (file)
index 0000000..ccd05fa
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-30225.rs:31:9
+   |
+LL |     u = v; // mark $0 and $1 in a subtype relationship
+   |         ^ expected struct `A`, found struct `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-43189-a.rs
new file mode 100644 (file)
index 0000000..9ab570f
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_type="lib"]
+
+
+pub trait A {
+    fn a(&self) {}
+}
+impl A for () {}
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-43189-b.rs
new file mode 100644 (file)
index 0000000..31dfb05
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_type="lib"]
+
+pub extern crate xcrate_issue_43189_a;
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs
new file mode 100644 (file)
index 0000000..2b517b5
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_type="lib"]
+
+pub extern crate core;
diff --git a/src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs b/src/test/ui/typeck/auxiliary/xcrate-issue-61711-b.rs
new file mode 100644 (file)
index 0000000..88a0405
--- /dev/null
@@ -0,0 +1,5 @@
+// edition:2018
+#![crate_type="lib"]
+#![crate_name="xcrate_issue_61711_b"]
+pub struct Struct;
+pub use crate as alias;
diff --git a/src/test/ui/typeck/issue-43189.rs b/src/test/ui/typeck/issue-43189.rs
new file mode 100644 (file)
index 0000000..ce667a5
--- /dev/null
@@ -0,0 +1,12 @@
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-43189-a.rs
+// aux-build:xcrate-issue-43189-b.rs
+
+extern crate xcrate_issue_43189_b;
+fn main() {
+    ().a();
+    //~^ ERROR no method named `a` found
+}
diff --git a/src/test/ui/typeck/issue-43189.stderr b/src/test/ui/typeck/issue-43189.stderr
new file mode 100644 (file)
index 0000000..caf7530
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0599]: no method named `a` found for unit type `()` in the current scope
+  --> $DIR/issue-43189.rs:10:8
+   |
+LL |     ().a();
+   |        ^ method not found in `()`
+   |
+  ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
+   |
+LL |     fn a(&self) {}
+   |        - the method is available for `()` here
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/typeck/issue-46112.rs b/src/test/ui/typeck/issue-46112.rs
new file mode 100644 (file)
index 0000000..0cdd2c2
--- /dev/null
@@ -0,0 +1,10 @@
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-46112-rexport-core.rs
+
+extern crate xcrate_issue_46112_rexport_core;
+fn test(r: Result<Option<()>, &'static str>) { }
+fn main() { test(Ok(())); }
+//~^ mismatched types
diff --git a/src/test/ui/typeck/issue-46112.stderr b/src/test/ui/typeck/issue-46112.stderr
new file mode 100644 (file)
index 0000000..ec05fbe
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-46112.rs:9:21
+   |
+LL | fn main() { test(Ok(())); }
+   |                     ^^
+   |                     |
+   |                     expected enum `Option`, found `()`
+   |                     help: try using a variant of the expected enum: `Some(())`
+   |
+   = note:   expected enum `Option<()>`
+           found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs
new file mode 100644 (file)
index 0000000..de7d6a0
--- /dev/null
@@ -0,0 +1,11 @@
+// Issue 61711: A crate pub re-exporting `crate` was causing an
+// infinite loop.
+
+// edition:2018
+// aux-build:xcrate-issue-61711-b.rs
+// compile-flags:--extern xcrate_issue_61711_b
+
+// build-pass
+
+fn f<F: Fn(xcrate_issue_61711_b::Struct)>(_: F) { }
+fn main() { }
diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs
new file mode 100644 (file)
index 0000000..74e50d4
--- /dev/null
@@ -0,0 +1,14 @@
+// edition:2021
+
+mod m {
+  pub struct S { foo: i32 }
+  impl S {
+    pub fn foo(&self) -> i32 { 42 }
+  }
+}
+
+fn bar(s: &m::S) {
+  || s.foo() + s.foo; //~ ERROR E0616
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr
new file mode 100644 (file)
index 0000000..02cdc10
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0616]: field `foo` of struct `S` is private
+  --> $DIR/issue-90483-inaccessible-field-adjustment.rs:11:18
+   |
+LL |   || s.foo() + s.foo;
+   |                  ^^^ private field
+   |
+help: a method `foo` also exists, call it with parentheses
+   |
+LL |   || s.foo() + s.foo();
+   |                     ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
diff --git a/src/test/ui/unary-minus-suffix-inference.rs b/src/test/ui/unary-minus-suffix-inference.rs
deleted file mode 100644 (file)
index a4d0a84..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-
-pub fn main() {
-    let a = 1;
-    let a_neg: i8 = -a;
-    println!("{}", a_neg);
-
-    let b = 1;
-    let b_neg: i16 = -b;
-    println!("{}", b_neg);
-
-    let c = 1;
-    let c_neg: i32 = -c;
-    println!("{}", c_neg);
-
-    let d = 1;
-    let d_neg: i64 = -d;
-    println!("{}", d_neg);
-
-    let e = 1;
-    let e_neg: isize = -e;
-    println!("{}", e_neg);
-}
diff --git a/src/test/ui/unboxed-closures/issue-18652.rs b/src/test/ui/unboxed-closures/issue-18652.rs
new file mode 100644 (file)
index 0000000..59aa015
--- /dev/null
@@ -0,0 +1,10 @@
+// run-pass
+// Tests multiple free variables being passed by value into an unboxed
+// once closure as an optimization by codegen.  This used to hit an
+// incorrect assert.
+
+fn main() {
+    let x = 2u8;
+    let y = 3u8;
+    assert_eq!((move || x + y)(), 5);
+}
diff --git a/src/test/ui/unnecessary-extern-crate.rs b/src/test/ui/unnecessary-extern-crate.rs
deleted file mode 100644 (file)
index 67eaaf4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// edition:2018
-
-#![deny(unused_extern_crates)]
-#![feature(test, rustc_private, crate_visibility_modifier)]
-
-extern crate libc;
-//~^ ERROR unused extern crate
-//~| HELP remove
-extern crate libc as x;
-//~^ ERROR unused extern crate
-//~| HELP remove
-
-extern crate proc_macro;
-
-#[macro_use]
-extern crate test;
-
-pub extern crate test as y;
-
-pub extern crate alloc;
-
-pub(crate) extern crate alloc as a;
-
-crate extern crate alloc as b;
-
-mod foo {
-    pub(in crate::foo) extern crate alloc as c;
-
-    pub(super) extern crate alloc as d;
-
-    extern crate libc;
-    //~^ ERROR unused extern crate
-    //~| HELP remove
-
-    extern crate libc as x;
-    //~^ ERROR unused extern crate
-    //~| HELP remove
-
-    pub extern crate test;
-
-    pub extern crate test as y;
-
-    mod bar {
-        extern crate libc;
-        //~^ ERROR unused extern crate
-        //~| HELP remove
-
-        extern crate libc as x;
-        //~^ ERROR unused extern crate
-        //~| HELP remove
-
-        pub(in crate::foo::bar) extern crate alloc as e;
-
-        fn dummy() {
-            e::string::String::new();
-        }
-    }
-
-    fn dummy() {
-        c::string::String::new();
-        d::string::String::new();
-    }
-}
-
-
-fn main() {
-    a::string::String::new();
-    b::string::String::new();
-
-    proc_macro::TokenStream::new();
-}
diff --git a/src/test/ui/unnecessary-extern-crate.stderr b/src/test/ui/unnecessary-extern-crate.stderr
deleted file mode 100644 (file)
index 14ba9d0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:6:1
-   |
-LL | extern crate libc;
-   | ^^^^^^^^^^^^^^^^^^ help: remove it
-   |
-note: the lint level is defined here
-  --> $DIR/unnecessary-extern-crate.rs:3:9
-   |
-LL | #![deny(unused_extern_crates)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:9:1
-   |
-LL | extern crate libc as x;
-   | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:31:5
-   |
-LL |     extern crate libc;
-   |     ^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:35:5
-   |
-LL |     extern crate libc as x;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:44:9
-   |
-LL |         extern crate libc;
-   |         ^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
-  --> $DIR/unnecessary-extern-crate.rs:48:9
-   |
-LL |         extern crate libc as x;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/unrestricted-attribute-tokens.rs b/src/test/ui/unrestricted-attribute-tokens.rs
deleted file mode 100644 (file)
index e31bc91..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// build-pass (FIXME(62277): could be check-pass?)
-
-#![feature(rustc_attrs)]
-
-#[rustc_dummy(a b c d)]
-#[rustc_dummy[a b c d]]
-#[rustc_dummy{a b c d}]
-fn main() {}
diff --git a/src/test/ui/unsized/issue-30355.rs b/src/test/ui/unsized/issue-30355.rs
new file mode 100644 (file)
index 0000000..6ff5b37
--- /dev/null
@@ -0,0 +1,9 @@
+pub struct X([u8]);
+
+pub static Y: &'static X = {
+    const Y: &'static [u8] = b"";
+    &X(*Y)
+    //~^ ERROR E0277
+};
+
+fn main() {}
diff --git a/src/test/ui/unsized/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr
new file mode 100644 (file)
index 0000000..71bbdf5
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-30355.rs:5:8
+   |
+LL |     &X(*Y)
+   |        ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 5fe85954dc8e98f3266d56a11a086e1c39b757bd..ca6b8ba94d1cab407a85482ac1695aebbe843f4f 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(use_nested_groups)]
 #![allow(dead_code)]
 #![deny(unused_imports)]
 
index 987d1dcf5f00de3e1b85d0b6e40f149945dcdd88..6610f8ecd4a28d5ee6290fa368335466b984f6d3 100644 (file)
@@ -1,23 +1,23 @@
 error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*`
-  --> $DIR/use-nested-groups-unused-imports.rs:16:11
+  --> $DIR/use-nested-groups-unused-imports.rs:15:11
    |
 LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *};
    |           ^^^        ^^^^^^^  ^^^^^^^^^   ^
    |
 note: the lint level is defined here
-  --> $DIR/use-nested-groups-unused-imports.rs:3:9
+  --> $DIR/use-nested-groups-unused-imports.rs:2:9
    |
 LL | #![deny(unused_imports)]
    |         ^^^^^^^^^^^^^^
 
 error: unused import: `*`
-  --> $DIR/use-nested-groups-unused-imports.rs:18:24
+  --> $DIR/use-nested-groups-unused-imports.rs:17:24
    |
 LL | use foo::bar::baz::{*, *};
    |                        ^
 
 error: unused import: `foo::{}`
-  --> $DIR/use-nested-groups-unused-imports.rs:20:5
+  --> $DIR/use-nested-groups-unused-imports.rs:19:5
    |
 LL | use foo::{};
    |     ^^^^^^^
diff --git a/src/test/ui/warn-ctypes-inhibit.rs b/src/test/ui/warn-ctypes-inhibit.rs
deleted file mode 100644 (file)
index 15d8b09..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-// compile-flags:-D improper-ctypes
-
-// pretty-expanded FIXME #23616
-#![allow(improper_ctypes)]
-
-mod libc {
-    extern "C" {
-        pub fn malloc(size: isize) -> *const u8;
-    }
-}
-
-pub fn main() {}
index 2bf4cfc50032049e780b88db39ab6fe47ca0dfd8..868923e5932438bf8b8c5d48c0093090e5a01acb 100644 (file)
@@ -28,10 +28,11 @@ pub fn main() {
           target_os = "emscripten",
           target_os = "freebsd",
           target_os = "fuchsia",
+          target_os = "illumos",
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "vxworks",
-          target_os = "solaris"))]
+          target_os = "solaris",
+          target_os = "vxworks"))]
 pub fn main() { }
diff --git a/src/test/ui/yield2.rs b/src/test/ui/yield2.rs
deleted file mode 100644 (file)
index 376faab..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-use std::thread;
-
-pub fn main() {
-    let mut i: isize = 0;
-    while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); }
-}
index 94ca096afbf25f670e76e07dca754fcfe27134be..2e2a16e983f597da62bc132eb191bc3276d4b1bb 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 94ca096afbf25f670e76e07dca754fcfe27134be
+Subproject commit 2e2a16e983f597da62bc132eb191bc3276d4b1bb
index 87ad5178ff0887d8971b220844b528659a251b8f..d4ba072807f8f891adb1de3f37b3327d5b9ea0eb 100644 (file)
@@ -5,7 +5,7 @@
 use clippy_utils::{is_entrypoint_fn, is_expn_of, match_panic_def_id, method_chain_args, return_ty};
 use if_chain::if_chain;
 use itertools::Itertools;
-use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
+use rustc_ast::ast::{Async, AttrKind, Attribute, Fn, FnRetTy, ItemKind};
 use rustc_ast::token::CommentKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
@@ -639,7 +639,7 @@ fn has_needless_main(code: String, edition: Edition) -> bool {
                             | ItemKind::ExternCrate(..)
                             | ItemKind::ForeignMod(..) => return false,
                             // We found a main function ...
-                            ItemKind::Fn(box FnKind(_, sig, _, Some(block))) if item.ident.name == sym::main => {
+                            ItemKind::Fn(box Fn { sig, body: Some(block), .. }) if item.ident.name == sym::main => {
                                 let is_async = matches!(sig.header.asyncness, Async::Yes { .. });
                                 let returns_nothing = match &sig.decl.output {
                                     FnRetTy::Default(..) => true,
index 476e6d23f12151e869270de3c8265bc647993d25..09b6e20083889e863ac884636ad2c3b20f08db50 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::in_macro;
-use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind};
+use rustc_ast::ast::{AssocItemKind, Extern, Fn, FnSig, Impl, Item, ItemKind, Trait, Ty, TyKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
@@ -162,17 +162,17 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
                     );
                 }
             },
-            ItemKind::Impl(box ImplKind {
+            ItemKind::Impl(box Impl {
                 of_trait: None, items, ..
             })
-            | ItemKind::Trait(box TraitKind(.., items)) => {
+            | ItemKind::Trait(box Trait { items, .. }) => {
                 for item in items {
-                    if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind {
-                        self.check_fn_sig(cx, fn_sig, item.span);
+                    if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
+                        self.check_fn_sig(cx, sig, item.span);
                     }
                 }
             },
-            ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span),
+            ItemKind::Fn(box Fn { sig, .. }) => self.check_fn_sig(cx, sig, item.span),
             _ => (),
         }
     }
index e18442515b8fc4ffaf10e5a2c6534e387fbc7551..6b2ac985555dc59fc7014b3c0afeb4267ffd9420 100644 (file)
@@ -77,13 +77,13 @@ fn check_fn(
             if is_future {
                 let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
-                let send_result = cx.tcx.infer_ctxt().enter(|infcx| {
+                let send_errors = cx.tcx.infer_ctxt().enter(|infcx| {
                     let cause = traits::ObligationCause::misc(span, hir_id);
                     let mut fulfillment_cx = traits::FulfillmentContext::new();
                     fulfillment_cx.register_bound(&infcx, cx.param_env, ret_ty, send_trait, cause);
                     fulfillment_cx.select_all_or_error(&infcx)
                 });
-                if let Err(send_errors) = send_result {
+                if !send_errors.is_empty() {
                     span_lint_and_then(
                         cx,
                         FUTURE_NOT_SEND,
index eb311983b29276ebf0b21b35ed9e0dcc46750af3..7142df98c3f10fde54afa98e822067dd468532f2 100644 (file)
@@ -1065,7 +1065,10 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
                 PatKind::Path(path) => {
                     #[allow(clippy::match_same_arms)]
                     let id = match cx.qpath_res(path, pat.hir_id) {
-                        Res::Def(DefKind::Const | DefKind::ConstParam | DefKind::AnonConst, _) => return,
+                        Res::Def(
+                            DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst,
+                            _,
+                        ) => return,
                         Res::Def(_, id) => id,
                         _ => return,
                     };
index 5b254bc8133d2fecce4c6227b90d7c91e2206b6c..e28cc49bf2a1a0f955ac3686c132d4c201b2b6ef 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use rustc_ast::ast::{
-    Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat, PatKind,
+    self, Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind,
 };
 use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -357,7 +357,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
             return;
         }
 
-        if let ItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
+        if let ItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind {
             do_check(self, cx, &item.attrs, &sig.decl, blk);
         }
     }
@@ -367,7 +367,7 @@ fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) {
             return;
         }
 
-        if let AssocItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
+        if let AssocItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind {
             do_check(self, cx, &item.attrs, &sig.decl, blk);
         }
     }
index 85d1f65c51f0911aaf1ab76ffb36ce496a759536..b412e15ae4f82c9b474f71837b84cb944ebbd23e 100644 (file)
@@ -4,7 +4,7 @@
 
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use rustc_ast::ast::{Expr, ExprKind, ImplKind, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
+use rustc_ast::ast::{Expr, ExprKind, Impl, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
 use rustc_ast::token::{self, LitKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_errors::Applicability;
@@ -243,7 +243,7 @@ pub struct Write {
 
 impl EarlyLintPass for Write {
     fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Impl(box ImplKind {
+        if let ItemKind::Impl(box Impl {
             of_trait: Some(trait_ref),
             ..
         }) = &item.kind
index 2fa98831c7740aa31e7765ddf463cb36eba3d658..1b05a8a35046ede0d99e4a5b439f52659ab2a075 100644 (file)
@@ -250,7 +250,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (Use(l), Use(r)) => eq_use_tree(l, r),
         (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
         (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
-        (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+        (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+         Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
         (Mod(lu, lmk), Mod(ru, rmk)) => {
@@ -266,7 +267,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (ForeignMod(l), ForeignMod(r)) => {
             both(&l.abi, &r.abi, eq_str_lit) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
         },
-        (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
@@ -276,7 +278,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
             eq_variant_data(lv, rv) && eq_generics(lg, rg)
         },
-        (Trait(box TraitKind(la, lu, lg, lb, li)), Trait(box TraitKind(ra, ru, rg, rb, ri))) => {
+        (Trait(box ast::Trait { is_auto: la, unsafety: lu, generics: lg, bounds: lb, items: li }),
+         Trait(box ast::Trait { is_auto: ra, unsafety: ru, generics: rg, bounds: rb, items: ri })) => {
             la == ra
                 && matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
                 && eq_generics(lg, rg)
@@ -285,7 +288,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
         },
         (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound),
         (
-            Impl(box ImplKind {
+            Impl(box ast::Impl {
                 unsafety: lu,
                 polarity: lp,
                 defaultness: ld,
@@ -295,7 +298,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 self_ty: lst,
                 items: li,
             }),
-            Impl(box ImplKind {
+            Impl(box ast::Impl {
                 unsafety: ru,
                 polarity: rp,
                 defaultness: rd,
@@ -325,10 +328,12 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
     use ForeignItemKind::*;
     match (l, r) {
         (Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
-        (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+        (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+         Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
-        (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
@@ -343,10 +348,12 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
     use AssocItemKind::*;
     match (l, r) {
         (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
-        (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+        (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+         Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
             eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
         },
-        (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+        (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+         TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
             eq_defaultness(*ld, *rd)
                 && eq_generics(lg, rg)
                 && over(lb, rb, eq_generic_bound)
index b3a9a1de2ec93daa57b44eace9a0d66d1781f6d3..733cc97c84596546bd0005ab6608749270564f7c 100644 (file)
@@ -3,12 +3,12 @@
 #![deny(clippy::missing_docs_in_private_items)]
 
 use crate::ty::is_type_diagnostic_item;
-use crate::{is_expn_of, last_path_segment, match_def_path, path_to_local_id, paths};
+use crate::{is_expn_of, last_path_segment, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitKind};
 use rustc_hir as hir;
 use rustc_hir::{
-    Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, PatKind, QPath, StmtKind, UnOp,
+    Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath, StmtKind, UnOp,
 };
 use rustc_lint::LateContext;
 use rustc_span::{sym, symbol, ExpnKind, Span, Symbol};
@@ -513,8 +513,6 @@ pub struct FormatArgsExpn<'tcx> {
     pub format_string_parts: &'tcx [Expr<'tcx>],
     /// Symbols corresponding to [`Self::format_string_parts`]
     pub format_string_symbols: Vec<Symbol>,
-    /// Match arm patterns, the `arg0`, etc. from the next field `args`
-    pub arg_names: &'tcx [Pat<'tcx>],
     /// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
     pub args: &'tcx [Expr<'tcx>],
     /// The final argument passed to `Arguments::new_v1_formatted`, if applicable
@@ -559,7 +557,6 @@ pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
                     _ => None,
                 })
                 .collect();
-            if let PatKind::Tuple(arg_names, None) = arm.pat.kind;
             if let ExprKind::Array(args) = arm.body.kind;
             then {
                 Some(FormatArgsExpn {
@@ -567,7 +564,6 @@ pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
                     value_args,
                     format_string_parts,
                     format_string_symbols,
-                    arg_names,
                     args,
                     fmt_expr,
                 })
@@ -594,10 +590,8 @@ pub fn args(&self) -> Option<Vec<FormatArgsArg<'tcx>>> {
                             if let Ok(i) = usize::try_from(position);
                             let arg = &self.args[i];
                             if let ExprKind::Call(_, [arg_name, _]) = arg.kind;
-                            if let Some(j) = self
-                                .arg_names
-                                .iter()
-                                .position(|pat| path_to_local_id(arg_name, pat.hir_id));
+                            if let ExprKind::Field(_, j) = arg_name.kind;
+                            if let Ok(j) = j.name.as_str().parse::<usize>();
                             then {
                                 Some(FormatArgsArg { value: self.value_args[j], arg, fmt: Some(fmt) })
                             } else {
index 9377eb69b233aca281df4305c86149d13f90b2f6..2498672d77fb04526208e6ec42d9eb8f2772156c 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(clippy::excessive_precision)]
 #[deny(clippy::unreadable_literal)]
 
 fn allow_inconsistent_digit_grouping() {
index 9119ef19a7be1aae36193412bcba84b58b204340..be505bda4792c757982e7c51566cbe6d672740d2 100644 (file)
@@ -1,5 +1,5 @@
 error: digits grouped inconsistently by underscores
-  --> $DIR/test.rs:18:18
+  --> $DIR/test.rs:19:18
    |
 LL |     let _fail1 = 100_200_300.123456789;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789`
index d4832daa6895970746de537909bb6339af07331e..9a150c67a21ea583cadad59326c607f33cb8b318 100644 (file)
@@ -52,12 +52,14 @@ macro_rules! m_mut {
     };
 }
 
+#[derive(Copy, Clone)]
 pub struct S;
 impl S {
     pub fn f(&self) -> &Self {
         m!(self)
     }
-    pub fn f_mut(&self) -> &Self {
+    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
+    pub fn f_mut(mut self) -> Self {
         m_mut!(self)
     }
 }
index be7cc669b5b6daf3c0cb855d6fe861e7920e943e..80ba7e9bd0b8202cbe9202343e3dd227000ff95f 100644 (file)
@@ -52,12 +52,14 @@ macro_rules! m_mut {
     };
 }
 
+#[derive(Copy, Clone)]
 pub struct S;
 impl S {
     pub fn f(&self) -> &Self {
         m!(self)
     }
-    pub fn f_mut(&self) -> &Self {
+    #[allow(unused_mut)] // mut will be unused, once the macro is fixed
+    pub fn f_mut(mut self) -> Self {
         m_mut!(self)
     }
 }
index d47dfcb5ba1eab1b8654a2c270700748923a4bee..38a8fbd74dcf61b540b16b34a496b9005d5ba800 100644 (file)
@@ -1,4 +1,5 @@
 #[warn(clippy::double_neg)]
+#[allow(clippy::no_effect)]
 fn main() {
     let x = 1;
     -x;
index d82ed05f0543dbf65a7fb5768c39ac7703561081..7cdb040b6873937266598277e48d240d796c95ca 100644 (file)
@@ -1,5 +1,5 @@
 error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op
-  --> $DIR/double_neg.rs:6:5
+  --> $DIR/double_neg.rs:7:5
    |
 LL |     --x;
    |     ^^^
index 7d6fd607e6545469dc9fa2e0286eae5417d00628..1442ee08e7546aa20056ccb5b3f27e894b6c4cb8 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::fn_params_excessive_bools)]
+#![allow(clippy::too_many_arguments)]
 
 extern "C" {
     fn f(_: bool, _: bool, _: bool, _: bool);
index 4e5dbc261d66bababa570af2a3b283536f668e45..cd9d07fa115d6d3bca7d24f8250925cb0a0aa879 100644 (file)
@@ -1,5 +1,5 @@
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:17:1
+  --> $DIR/fn_params_excessive_bools.rs:18:1
    |
 LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:20:1
+  --> $DIR/fn_params_excessive_bools.rs:21:1
    |
 LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | fn t(_: S, _: S, _: Box<S>, _: Vec<u32>, _: bool, _: bool, _: bool, _: bool
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:24:5
+  --> $DIR/fn_params_excessive_bools.rs:25:5
    |
 LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL |     fn f(_: bool, _: bool, _: bool, _: bool);
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:29:5
+  --> $DIR/fn_params_excessive_bools.rs:30:5
    |
 LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL |     fn f(&self, _: bool, _: bool, _: bool, _: bool) {}
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:41:5
+  --> $DIR/fn_params_excessive_bools.rs:42:5
    |
 LL | /     fn n(_: bool, _: u32, _: bool, _: Box<u32>, _: bool, _: bool) {
 LL | |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
@@ -42,7 +42,7 @@ LL | |     }
    = help: consider refactoring bools into two-variant enums
 
 error: more than 3 bools in function parameters
-  --> $DIR/fn_params_excessive_bools.rs:42:9
+  --> $DIR/fn_params_excessive_bools.rs:43:9
    |
 LL |         fn nn(_: bool, _: bool, _: bool, _: bool) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 0d14807ff1cfcf1f2745b521f0c101c7ca85eddb..471a8e0de6e193047e17ffa3e4273dce9799ac62 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(unused_assignments)]
 #![allow(clippy::if_same_then_else)]
 #![allow(clippy::deref_addrof)]
+#![allow(clippy::nonminimal_bool)]
 
 fn foo() -> bool {
     true
index bde434c7e2e78737ae451a9c8dd776712aba5090..9272cd6048441790c403e0750193c78fa6c56049 100644 (file)
@@ -1,5 +1,5 @@
 error: this looks like you are trying to use `.. -= ..`, but you really are doing `.. = (- ..)`
-  --> $DIR/formatting.rs:15:6
+  --> $DIR/formatting.rs:16:6
    |
 LL |     a =- 35;
    |      ^^^^
@@ -8,7 +8,7 @@ LL |     a =- 35;
    = note: to remove this lint, use either `-=` or `= -`
 
 error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)`
-  --> $DIR/formatting.rs:16:6
+  --> $DIR/formatting.rs:17:6
    |
 LL |     a =* &191;
    |      ^^^^
@@ -16,7 +16,7 @@ LL |     a =* &191;
    = note: to remove this lint, use either `*=` or `= *`
 
 error: this looks like you are trying to use `.. != ..`, but you really are doing `.. = (! ..)`
-  --> $DIR/formatting.rs:19:6
+  --> $DIR/formatting.rs:20:6
    |
 LL |     b =! false;
    |      ^^^^
@@ -24,7 +24,7 @@ LL |     b =! false;
    = note: to remove this lint, use either `!=` or `= !`
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:28:19
+  --> $DIR/formatting.rs:29:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
@@ -33,7 +33,7 @@ LL |         -1, -2, -3 // <= no comma here
    = note: to remove this lint, add a comma or write the expr in a single line
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:32:19
+  --> $DIR/formatting.rs:33:19
    |
 LL |         -1, -2, -3 // <= no comma here
    |                   ^
@@ -41,7 +41,7 @@ LL |         -1, -2, -3 // <= no comma here
    = note: to remove this lint, add a comma or write the expr in a single line
 
 error: possibly missing a comma here
-  --> $DIR/formatting.rs:69:11
+  --> $DIR/formatting.rs:70:11
    |
 LL |         -1
    |           ^
index e60ce8492fc7716f70f3f490086d03d76904f07f..0cadd5a3da1983e4436d9f946808a84aa45a55b7 100644 (file)
@@ -4,7 +4,7 @@
 #![warn(clippy::zero_prefixed_literal)]
 #![warn(clippy::unseparated_literal_suffix)]
 #![warn(clippy::separated_literal_suffix)]
-#![allow(dead_code)]
+#![allow(dead_code, overflowing_literals)]
 
 fn main() {
     let ok1 = 0xABCD;
index 65769819110eb6f00b05332c7ae0b54c6ba8fa2b..88fcce66873aa3a73b6194eeddcacc88762bffb7 100644 (file)
@@ -1,3 +1,4 @@
+#![allow(clippy::too_many_arguments, clippy::diverging_sub_expression)]
 #![warn(clippy::many_single_char_names)]
 
 fn bla() {
index 27e62e641ade9c2d3b208922bd7d3367c6d21f0a..ade0f84bc50653be1b7f4574e7ff5fc9afd35cd3 100644 (file)
@@ -1,5 +1,5 @@
 error: 5 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -12,7 +12,7 @@ LL |             let e: i32;
    = note: `-D clippy::many-single-char-names` implied by `-D warnings`
 
 error: 6 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -25,7 +25,7 @@ LL |             let f: i32;
    |                 ^
 
 error: 5 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:4:9
+  --> $DIR/many_single_char_names.rs:5:9
    |
 LL |     let a: i32;
    |         ^
@@ -36,13 +36,13 @@ LL |             e => panic!(),
    |             ^
 
 error: 8 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:29:13
+  --> $DIR/many_single_char_names.rs:30:13
    |
 LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {}
    |             ^       ^       ^       ^       ^       ^       ^       ^
 
 error: 8 bindings with single-character names in scope
-  --> $DIR/many_single_char_names.rs:32:10
+  --> $DIR/many_single_char_names.rs:33:10
    |
 LL |     let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!();
    |          ^  ^  ^  ^  ^  ^  ^  ^
index 70cdb067d91380cb2b8866110d8c4160a683c1e4..5d57638af43495bea12bce75b930aa600ae51343 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     unused_variables,
+    overflowing_literals,
     clippy::excessive_precision,
     clippy::inconsistent_digit_grouping
 )]
@@ -21,7 +22,6 @@ fn main() {
     let fail25 = 1E2_f32;
     let fail26 = 43E7_f64;
     let fail27 = 243E17_f32;
-    #[allow(overflowing_literals)]
     let fail28 = 241_251_235E723_f64;
     let ok29 = 42279.911_32;
 
index 729990af3998dbc9d36f0e40b3d8d93175da5009..12171452885d2b009bdb0e0373abe765a0c29a04 100644 (file)
@@ -3,6 +3,7 @@
 #![allow(
     dead_code,
     unused_variables,
+    overflowing_literals,
     clippy::excessive_precision,
     clippy::inconsistent_digit_grouping
 )]
@@ -21,7 +22,6 @@ fn main() {
     let fail25 = 1E2_32;
     let fail26 = 43E7_64;
     let fail27 = 243E17_32;
-    #[allow(overflowing_literals)]
     let fail28 = 241251235E723_64;
     let ok29 = 42279.911_32;
 
index b338b8aa6228d5757cc7c79212f6c48bd0b2f1b9..d24543c26e4b0d7e48cbb4647f03ebcd2abf3cb0 100644 (file)
@@ -1,5 +1,5 @@
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:11:18
+  --> $DIR/mistyped_literal_suffix.rs:12:18
    |
 LL |     let fail14 = 2_32;
    |                  ^^^^ help: did you mean to write: `2_i32`
@@ -7,49 +7,49 @@ LL |     let fail14 = 2_32;
    = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:12:18
+  --> $DIR/mistyped_literal_suffix.rs:13:18
    |
 LL |     let fail15 = 4_64;
    |                  ^^^^ help: did you mean to write: `4_i64`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:13:18
+  --> $DIR/mistyped_literal_suffix.rs:14:18
    |
 LL |     let fail16 = 7_8; //
    |                  ^^^ help: did you mean to write: `7_i8`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:14:18
+  --> $DIR/mistyped_literal_suffix.rs:15:18
    |
 LL |     let fail17 = 23_16; //
    |                  ^^^^^ help: did you mean to write: `23_i16`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:17:18
+  --> $DIR/mistyped_literal_suffix.rs:18:18
    |
 LL |     let fail20 = 2__8; //
    |                  ^^^^ help: did you mean to write: `2_i8`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:18:18
+  --> $DIR/mistyped_literal_suffix.rs:19:18
    |
 LL |     let fail21 = 4___16; //
    |                  ^^^^^^ help: did you mean to write: `4_i16`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:21:18
+  --> $DIR/mistyped_literal_suffix.rs:22:18
    |
 LL |     let fail25 = 1E2_32;
    |                  ^^^^^^ help: did you mean to write: `1E2_f32`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:22:18
+  --> $DIR/mistyped_literal_suffix.rs:23:18
    |
 LL |     let fail26 = 43E7_64;
    |                  ^^^^^^^ help: did you mean to write: `43E7_f64`
 
 error: mistyped literal suffix
-  --> $DIR/mistyped_literal_suffix.rs:23:18
+  --> $DIR/mistyped_literal_suffix.rs:24:18
    |
 LL |     let fail27 = 243E17_32;
    |                  ^^^^^^^^^ help: did you mean to write: `243E17_f32`
index a39d96109f17d8d03e38c4701cc4345d1e51ed30..ad0d694a2174a3a125393790d5767a81afd9c98d 100644 (file)
@@ -38,6 +38,7 @@ struct S2 {}
     //  fn call_with_mut_self<'life0>(self: &'life0 mut Self) {}
     #[rename_my_lifetimes]
     impl T2 for S2 {
+        #[allow(clippy::needless_lifetimes)]
         fn call_with_mut_self(self: &mut Self) {}
     }
 }
index 44a0e6ddeace63bcd54bc6f7284eff4a336ec4e9..b2edbfe4323e16ce6ec4407158daa60f143b335f 100644 (file)
@@ -1,5 +1,5 @@
 error: the type of the `self` parameter does not need to be arbitrary
-  --> $DIR/needless_arbitrary_self_type_unfixable.rs:41:31
+  --> $DIR/needless_arbitrary_self_type_unfixable.rs:42:31
    |
 LL |         fn call_with_mut_self(self: &mut Self) {}
    |                               ^^^^^^^^^^^^^^^ help: consider to change this parameter to: `&'_ mut self`
index 83ee27f4887a1822d7aa6ae1eb1deca3fc29edba..f105d3d659ac7fb199e5c4fc593ca224c86447e1 100644 (file)
@@ -12,6 +12,7 @@ macro_rules! nonzero {
     };
 }
 
+#[allow(clippy::nonminimal_bool)]
 fn main() {
     let mut i = 1;
     while i < 10 {
index 22b86f25e8f0e44ced23329d1cc378cc31d27e89..b8657c74caa6930c9408ecc4079a9fd7b5893e0d 100644 (file)
@@ -1,5 +1,5 @@
 error: this `else` block is redundant
-  --> $DIR/needless_continue.rs:28:16
+  --> $DIR/needless_continue.rs:29:16
    |
 LL |           } else {
    |  ________________^
@@ -35,7 +35,7 @@ LL | |         }
                    }
 
 error: there is no need for an explicit `else` block for this `if` expression
-  --> $DIR/needless_continue.rs:43:9
+  --> $DIR/needless_continue.rs:44:9
    |
 LL | /         if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
 LL | |             continue;
@@ -55,7 +55,7 @@ LL | |         }
                    }
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:56:9
+  --> $DIR/needless_continue.rs:57:9
    |
 LL |         continue; // should lint here
    |         ^^^^^^^^^
@@ -63,7 +63,7 @@ LL |         continue; // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:63:9
+  --> $DIR/needless_continue.rs:64:9
    |
 LL |         continue; // should lint here
    |         ^^^^^^^^^
@@ -71,7 +71,7 @@ LL |         continue; // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:70:9
+  --> $DIR/needless_continue.rs:71:9
    |
 LL |         continue // should lint here
    |         ^^^^^^^^
@@ -79,7 +79,7 @@ LL |         continue // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `continue` expression is redundant
-  --> $DIR/needless_continue.rs:78:9
+  --> $DIR/needless_continue.rs:79:9
    |
 LL |         continue // should lint here
    |         ^^^^^^^^
@@ -87,7 +87,7 @@ LL |         continue // should lint here
    = help: consider dropping the `continue` expression
 
 error: this `else` block is redundant
-  --> $DIR/needless_continue.rs:128:24
+  --> $DIR/needless_continue.rs:129:24
    |
 LL |                   } else {
    |  ________________________^
@@ -110,7 +110,7 @@ LL | |                 }
                            }
 
 error: there is no need for an explicit `else` block for this `if` expression
-  --> $DIR/needless_continue.rs:134:17
+  --> $DIR/needless_continue.rs:135:17
    |
 LL | /                 if condition() {
 LL | |                     continue; // should lint here
index 961f6f409ddd2202916bfe14c17111d208359592..9937005d68d8ae43092952b1a4f307d8f21f816c 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::all)]
-#![allow(unused, clippy::println_empty_string)]
+#![allow(unused, clippy::println_empty_string, non_snake_case)]
 
 #[derive(Clone, Debug)]
 enum MaybeInst {
@@ -14,6 +14,7 @@ struct InstSplit {
 
 impl MaybeInst {
     fn fill(&mut self) {
+        #[allow(non_fmt_panics)]
         let filled = match *self {
             MaybeInst::Split1(goto1) => panic!("1"),
             MaybeInst::Split2(goto2) => panic!("2"),
@@ -36,6 +37,7 @@ fn issue2927() {
 }
 
 fn issue3078() {
+    #[allow(clippy::single_match)]
     match "a" {
         stringify!(a) => {},
         _ => {},
index a0ca46f0efc602cd0a6bccc6c35b48dee5697e5e..116d5da8729c0f2d334d91a4966483158f52bd53 100644 (file)
@@ -1,5 +1,5 @@
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:27:9
+  --> $DIR/non_expressive_names.rs:28:9
    |
 LL |     let _1 = 1; //~ERROR Consider a more descriptive name
    |         ^^
@@ -7,31 +7,31 @@ LL |     let _1 = 1; //~ERROR Consider a more descriptive name
    = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings`
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:28:9
+  --> $DIR/non_expressive_names.rs:29:9
    |
 LL |     let ____1 = 1; //~ERROR Consider a more descriptive name
    |         ^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:29:9
+  --> $DIR/non_expressive_names.rs:30:9
    |
 LL |     let __1___2 = 12; //~ERROR Consider a more descriptive name
    |         ^^^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:49:13
+  --> $DIR/non_expressive_names.rs:51:13
    |
 LL |         let _1 = 1;
    |             ^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:50:13
+  --> $DIR/non_expressive_names.rs:52:13
    |
 LL |         let ____1 = 1;
    |             ^^^^^
 
 error: consider choosing a more descriptive name
-  --> $DIR/non_expressive_names.rs:51:13
+  --> $DIR/non_expressive_names.rs:53:13
    |
 LL |         let __1___2 = 12;
    |             ^^^^^^^
index 3dd365620ccbf1b4f4eef131819ce9da695f84dd..5649d8dd14c4899fde03e7a75d78bf5309aa4728 100644 (file)
@@ -15,5 +15,6 @@ fn main() {
     #[allow(clippy::needless_return)]
     (|| return 2)();
     (|| -> Option<i32> { None? })();
+    #[allow(clippy::try_err)]
     (|| -> Result<i32, i32> { Err(2)? })();
 }
index 737c8a9f8db43783313ab6d6fdfbfe0341709984..e8a6e940c01cdbebd76dfcceb066bafea11d97cc 100644 (file)
@@ -1,5 +1,5 @@
 #![warn(clippy::redundant_else)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::if_same_then_else)]
 
 fn main() {
     loop {
@@ -105,7 +105,7 @@ fn main() {
         1
     };
     // assign
-    let a;
+    let mut a;
     a = if foo() {
         return;
     } else {
index daa073414577c8bfd897f37fe8b9a944eb063fe3..76f6ce9ee6b47f3826824a35e2495c0513d80c23 100644 (file)
@@ -1,5 +1,10 @@
 #![warn(clippy::similar_names)]
-#![allow(unused, clippy::println_empty_string)]
+#![allow(
+    unused,
+    clippy::println_empty_string,
+    clippy::empty_loop,
+    clippy::diverging_sub_expression
+)]
 
 struct Foo {
     apple: i32,
index f621595abaea2ee295423dbcb04b990f63b7184c..faf572b0c6bc27010c8af554b37cd863e295ab2a 100644 (file)
@@ -1,84 +1,84 @@
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:15:9
+  --> $DIR/similar_names.rs:20:9
    |
 LL |     let bpple: i32;
    |         ^^^^^
    |
    = note: `-D clippy::similar-names` implied by `-D warnings`
 note: existing binding defined here
-  --> $DIR/similar_names.rs:13:9
+  --> $DIR/similar_names.rs:18:9
    |
 LL |     let apple: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:17:9
+  --> $DIR/similar_names.rs:22:9
    |
 LL |     let cpple: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:13:9
+  --> $DIR/similar_names.rs:18:9
    |
 LL |     let apple: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:41:9
+  --> $DIR/similar_names.rs:46:9
    |
 LL |     let bluby: i32;
    |         ^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:40:9
+  --> $DIR/similar_names.rs:45:9
    |
 LL |     let blubx: i32;
    |         ^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:45:9
+  --> $DIR/similar_names.rs:50:9
    |
 LL |     let coke: i32;
    |         ^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:43:9
+  --> $DIR/similar_names.rs:48:9
    |
 LL |     let cake: i32;
    |         ^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:63:9
+  --> $DIR/similar_names.rs:68:9
    |
 LL |     let xyzeabc: i32;
    |         ^^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:61:9
+  --> $DIR/similar_names.rs:66:9
    |
 LL |     let xyz1abc: i32;
    |         ^^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:67:9
+  --> $DIR/similar_names.rs:72:9
    |
 LL |     let parsee: i32;
    |         ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:65:9
+  --> $DIR/similar_names.rs:70:9
    |
 LL |     let parser: i32;
    |         ^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:88:16
+  --> $DIR/similar_names.rs:93:16
    |
 LL |         bpple: sprang,
    |                ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:87:16
+  --> $DIR/similar_names.rs:92:16
    |
 LL |         apple: spring,
    |                ^^^^^^
index be8bc22bf98a05d062caff083c4c6e1d1d903c85..fcd827a91c7f62d843bfd47a30016a58e9dbbf2d 100644 (file)
@@ -1,6 +1,7 @@
 // aux-build:proc_macro_suspicious_else_formatting.rs
 
 #![warn(clippy::suspicious_else_formatting)]
+#![allow(clippy::if_same_then_else)]
 
 extern crate proc_macro_suspicious_else_formatting;
 use proc_macro_suspicious_else_formatting::DeriveBadSpan;
index d1db195cbb8787bc0003738f2f2c1e37adbf7fe3..ee68eb5a791c45d5ea2c5c3ab4edc2fe8810fc35 100644 (file)
@@ -1,5 +1,5 @@
 error: this looks like an `else {..}` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:16:6
+  --> $DIR/suspicious_else_formatting.rs:17:6
    |
 LL |     } {
    |      ^
@@ -8,7 +8,7 @@ LL |     } {
    = note: to remove this lint, add the missing `else` or add a new line before the next block
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:20:6
+  --> $DIR/suspicious_else_formatting.rs:21:6
    |
 LL |     } if foo() {
    |      ^
@@ -16,7 +16,7 @@ LL |     } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:27:10
+  --> $DIR/suspicious_else_formatting.rs:28:10
    |
 LL |         } if foo() {
    |          ^
@@ -24,7 +24,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this looks like an `else if` but the `else` is missing
-  --> $DIR/suspicious_else_formatting.rs:35:10
+  --> $DIR/suspicious_else_formatting.rs:36:10
    |
 LL |         } if foo() {
    |          ^
@@ -32,7 +32,7 @@ LL |         } if foo() {
    = note: to remove this lint, add the missing `else` or add a new line before the second `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:44:6
+  --> $DIR/suspicious_else_formatting.rs:45:6
    |
 LL |       } else
    |  ______^
@@ -42,7 +42,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:56:6
+  --> $DIR/suspicious_else_formatting.rs:57:6
    |
 LL |       } else
    |  ______^
@@ -52,7 +52,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else if` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:61:6
+  --> $DIR/suspicious_else_formatting.rs:62:6
    |
 LL |       }
    |  ______^
@@ -63,7 +63,7 @@ LL | |     if foo() { // the span of the above error should continue here
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `if`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:88:6
+  --> $DIR/suspicious_else_formatting.rs:89:6
    |
 LL |       }
    |  ______^
@@ -75,7 +75,7 @@ LL | |     {
    = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}`
 
 error: this is an `else {..}` but the formatting might hide it
-  --> $DIR/suspicious_else_formatting.rs:96:6
+  --> $DIR/suspicious_else_formatting.rs:97:6
    |
 LL |       }
    |  ______^
index 2f8c7cec50f8ec47f1802a554e3d381a859ba3a3..3201d5de0f35620663dea65c8903b481d8ac9eb6 100644 (file)
@@ -1,4 +1,5 @@
 #![warn(clippy::suspicious_operation_groupings)]
+#![allow(clippy::eq_op)]
 
 struct Vec3 {
     x: f64,
@@ -187,7 +188,7 @@ fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool {
     }
 }
 
-fn inside_an_if_statement(s1: &S, s2: &S) {
+fn inside_an_if_statement(s1: &mut S, s2: &S) {
     // There's no `s1.b`
     if s1.a < s2.a && s1.a < s2.b {
         s1.c = s2.c;
index dd6f2f6641d678b14b1d401fac951d98ce43f913..baf9bc74b000ec30468a9e08112d1decaed61346 100644 (file)
@@ -1,5 +1,5 @@
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:14:9
+  --> $DIR/suspicious_operation_groupings.rs:15:9
    |
 LL |         self.x == other.y && self.y == other.y && self.z == other.z
    |         ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
@@ -7,151 +7,151 @@ LL |         self.x == other.y && self.y == other.y && self.z == other.z
    = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:27:20
+  --> $DIR/suspicious_operation_groupings.rs:28:20
    |
 LL |     s1.a < s2.a && s1.a < s2.b
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:75:33
+  --> $DIR/suspicious_operation_groupings.rs:76:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:80:19
+  --> $DIR/suspicious_operation_groupings.rs:81:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:80:19
+  --> $DIR/suspicious_operation_groupings.rs:81:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:85:19
+  --> $DIR/suspicious_operation_groupings.rs:86:19
    |
 LL |     s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:90:19
+  --> $DIR/suspicious_operation_groupings.rs:91:19
    |
 LL |     s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:95:5
+  --> $DIR/suspicious_operation_groupings.rs:96:5
    |
 LL |     s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
    |     ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:100:33
+  --> $DIR/suspicious_operation_groupings.rs:101:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:113:20
+  --> $DIR/suspicious_operation_groupings.rs:114:20
    |
 LL |     (s1.a * s2.a + s1.b * s1.b)
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:118:34
+  --> $DIR/suspicious_operation_groupings.rs:119:34
    |
 LL |     (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
    |                                  ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:123:38
+  --> $DIR/suspicious_operation_groupings.rs:124:38
    |
 LL |     (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
    |                                      ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:128:39
+  --> $DIR/suspicious_operation_groupings.rs:129:39
    |
 LL |     ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
    |                                       ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:133:42
+  --> $DIR/suspicious_operation_groupings.rs:134:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:133:42
+  --> $DIR/suspicious_operation_groupings.rs:134:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:138:40
+  --> $DIR/suspicious_operation_groupings.rs:139:40
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:143:40
+  --> $DIR/suspicious_operation_groupings.rs:144:40
    |
 LL |     ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:148:20
+  --> $DIR/suspicious_operation_groupings.rs:149:20
    |
 LL |     (s1.a * s2.a + s2.b * s2.b) / 2
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:153:35
+  --> $DIR/suspicious_operation_groupings.rs:154:35
    |
 LL |     i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
    |                                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:158:29
+  --> $DIR/suspicious_operation_groupings.rs:159:29
    |
 LL |     s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
    |                             ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:163:17
+  --> $DIR/suspicious_operation_groupings.rs:164:17
    |
 LL |     s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
    |                 ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:172:77
+  --> $DIR/suspicious_operation_groupings.rs:173:77
    |
 LL |     (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
    |                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:186:25
+  --> $DIR/suspicious_operation_groupings.rs:187:25
    |
 LL |         s1.a <= s2.a && s1.a <= s2.b
    |                         ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:192:23
+  --> $DIR/suspicious_operation_groupings.rs:193:23
    |
 LL |     if s1.a < s2.a && s1.a < s2.b {
    |                       ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:199:48
+  --> $DIR/suspicious_operation_groupings.rs:200:48
    |
 LL |     -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
    |                                                ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:204:27
+  --> $DIR/suspicious_operation_groupings.rs:205:27
    |
 LL |     -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
    |                           ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`
index d03c21dc5086fe499e14d94d00e366669467955a..6ca145a58e92af169c4c2004dc5e524c2038a0a7 100644 (file)
 ];
 
 static ASM_SUPPORTED_ARCHS: &[&str] = &[
-    "x86", "x86_64", "arm", "aarch64", "riscv32", "riscv64", "nvptx64", "hexagon", "mips",
-    "mips64", "spirv", "wasm32",
+    "x86", "x86_64", "arm", "aarch64", "riscv32",
+    "riscv64",
+    // These targets require an additional asm_experimental_arch feature.
+    // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32",
 ];
 
 pub fn has_asm_support(triple: &str) -> bool {
index 7bdf527d8842bbedba3da1795ea5a4bd8b57a165..f52fbdfe2d7dc5949b5195985598a0c3bc335747 100644 (file)
@@ -79,11 +79,34 @@ fn find_all_html_files(dir: &Path) -> (usize, usize) {
     (files_read, errors)
 }
 
+/// Default `tidy` command for macOS is too old that it does not have `mute-id` and `mute` options.
+/// `tidy` on macOS Monterey was released on 31 October 2006, and the same date can be seen seven
+/// years ago at <https://stackoverflow.com/questions/22283382/overwrite-osx-tidy>. Accordingly,
+/// the macOS environment using pre-installed `tidy` should immediately suspend HTML checker process
+/// and show a hint to install a newer one.
+#[cfg(target_os = "macos")]
+fn check_tidy_version() -> Result<(), String> {
+    let output = Command::new("tidy").arg("-v").output().expect("failed to run tidy command");
+    let version = String::from_utf8(output.stdout).expect("failed to read version of tidy command");
+    if version.contains("HTML Tidy for Mac OS X released on 31 October 2006") {
+        eprintln!("The pre-installed HTML Tidy for macOS is not supported.");
+        eprintln!("Consider installing a newer one and re-running.");
+        eprintln!("If you're using Homebrew, you can install it by the following command:");
+        eprintln!("    brew install tidy-html5");
+        eprintln!();
+        Err("HTML check failed: 1 error".to_string())
+    } else {
+        Ok(())
+    }
+}
+
 fn main() -> Result<(), String> {
     let args = env::args().collect::<Vec<_>>();
     if args.len() != 2 {
         return Err(format!("Usage: {} <doc folder>", args[0]));
     }
+    #[cfg(target_os = "macos")]
+    check_tidy_version()?;
 
     println!("Running HTML checker...");
 
index 9c18177cd36fe07a3c251234240a9c77a4e66785..a8b976eb350acec83280a0cd1ca3ac99faff67bc 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9c18177cd36fe07a3c251234240a9c77a4e66785
+Subproject commit a8b976eb350acec83280a0cd1ca3ac99faff67bc
index 04f03a360ab8fef3d9c0ff84de2d39b8a196c717..2c0f433fd2e838ae181f87019b6f1fefe33c6f54 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 04f03a360ab8fef3d9c0ff84de2d39b8a196c717
+Subproject commit 2c0f433fd2e838ae181f87019b6f1fefe33c6f54
index a673e425dfff9d41610b59ae14f014486f911018..4f73a7f634098f2f7d6846e593a083c24877fcb4 100644 (file)
@@ -401,7 +401,8 @@ function showHelp() {
     console.log("  --doc-folder [PATH]        : location of the generated doc folder");
     console.log("  --help                     : show this message then quit");
     console.log("  --crate-name [STRING]      : crate name to be used");
-    console.log("  --test-file [PATH]         : location of the JS test file");
+    console.log("  --test-file [PATHs]        : location of the JS test files (can be called " +
+                "multiple times)");
     console.log("  --test-folder [PATH]       : location of the JS tests folder");
     console.log("  --resource-suffix [STRING] : suffix to refer to the correct files");
 }
@@ -412,7 +413,7 @@ function parseOptions(args) {
         "resource_suffix": "",
         "doc_folder": "",
         "test_folder": "",
-        "test_file": "",
+        "test_file": [],
     };
     var correspondences = {
         "--resource-suffix": "resource_suffix",
@@ -429,7 +430,11 @@ function parseOptions(args) {
                 console.log("Missing argument after `" + args[i - 1] + "` option.");
                 return null;
             }
-            opts[correspondences[args[i - 1]]] = args[i];
+            if (args[i - 1] !== "--test-file") {
+                opts[correspondences[args[i - 1]]] = args[i];
+            } else {
+                opts[correspondences[args[i - 1]]].push(args[i]);
+            }
         } else if (args[i] === "--help") {
             showHelp();
             process.exit(0);
@@ -471,9 +476,10 @@ function main(argv) {
     var errors = 0;
 
     if (opts["test_file"].length !== 0) {
-        errors += checkFile(opts["test_file"], opts, loaded, index);
-    }
-    if (opts["test_folder"].length !== 0) {
+        opts["test_file"].forEach(function(file) {
+            errors += checkFile(file, opts, loaded, index);
+        });
+    } else if (opts["test_folder"].length !== 0) {
         fs.readdirSync(opts["test_folder"]).forEach(function(file) {
             if (!file.endsWith(".js")) {
                 return;
diff --git a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
new file mode 100644 (file)
index 0000000..ca96d30
--- /dev/null
@@ -0,0 +1,25 @@
+name: rustdoc check
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+
+jobs:
+  rustdoc_check:
+    runs-on: ubuntu-latest
+    name: rustdoc check
+    steps:
+    - name: checkout
+      uses: actions/checkout@v2
+
+    - name: install rustup
+      run: |
+        curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
+        sh rustup-init.sh -y --default-toolchain none
+        rustup target add x86_64-unknown-linux-gnu
+
+    - name: document rustfmt
+      env:
+        RUSTDOCFLAGS: --document-private-items --enable-index-page --show-type-layout --generate-link-to-definition -Zunstable-options -Dwarnings
+      run: cargo doc -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro
index 7a77dbe154b60f2f55224cfeae2cb41f2127c53c..13826883d2f4bdf537df1df2a687be215adbaf97 100644 (file)
@@ -2062,7 +2062,7 @@ use sit;
 Controls the strategy for how imports are grouped together.
 
 - **Default value**: `Preserve`
-- **Possible values**: `Preserve`, `StdExternalCrate`
+- **Possible values**: `Preserve`, `StdExternalCrate`, `One`
 - **Stable**: No
 
 #### `Preserve` (default):
@@ -2108,6 +2108,23 @@ use super::update::convert_publish_payload;
 use crate::models::Event;
 ```
 
+#### `One`:
+
+Discard existing import groups, and create a single group for everything
+
+```rust
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
+```
+
 ## `reorder_modules`
 
 Reorder `mod` declarations alphabetically in group.
index e6dc6a220376db13aaea6aa795410a1c37a851c7..3073996019ee26be58d1ec8aaa233545ee8803d9 100644 (file)
@@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file
 ## Debugging
 
 Some `rewrite_*` methods use the `debug!` macro for printing useful information.
-These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`.
+These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`.
 These traces can be helpful in understanding which part of the code was used
 and get a better grasp on the execution flow.
 
index 9c7a1c4bc341bed77ce3ee362a8eea5d01ad7974..b3d21e6fb87c79ffa3957b20a4cc405f2787f051 100644 (file)
@@ -47,7 +47,7 @@ cargo +nightly fmt
 
 ## Limitations
 
-Rustfmt tries to work on as much Rust code as possible, sometimes, the code
+Rustfmt tries to work on as much Rust code as possible. Sometimes, the code
 doesn't even need to compile! As we approach a 1.0 release we are also looking
 to limit areas of instability; in particular, post-1.0, the formatting of most
 code should not change as Rustfmt improves. However, there are some things that
@@ -102,6 +102,25 @@ read data from stdin. Alternatively, you can use `cargo fmt` to format all
 binary and library targets of your crate.
 
 You can run `rustfmt --help` for information about available arguments.
+The easiest way to run rustfmt against a project is with `cargo fmt`. `cargo fmt` works on both
+single-crate projects and [cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html).
+Please see `cargo fmt --help` for usage information.
+
+You can specify the path to your own `rustfmt` binary for cargo to use by setting the`RUSTFMT` 
+environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (`cargo fmt --version`)
+
+### Running `rustfmt` directly
+
+To format individual files or arbitrary codes from stdin, the `rustfmt` binary should be used. Some
+examples follow:
+
+- `rustfmt lib.rs main.rs` will format "lib.rs" and "main.rs" in place
+- `rustfmt` will read a code from stdin and write formatting to stdout
+  - `echo "fn     main() {}" | rustfmt` would emit "fn main() {}".
+
+For more information, including arguments and emit options, see `rustfmt --help`.
+
+### Verifying code is formatted
 
 When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not
 make any formatting changes to the input, and `1` if Rustfmt would make changes.
@@ -129,7 +148,7 @@ rustfmt to exit with an error code if the input is not formatted correctly.
 It will also print any found differences. (Older versions of Rustfmt don't
 support `--check`, use `--write-mode diff`).
 
-A minimal Travis setup could look like this (requires Rust 1.24.0 or greater):
+A minimal Travis setup could look like this (requires Rust 1.31.0 or greater):
 
 ```yaml
 language: rust
diff --git a/src/tools/rustfmt/appveyor.yml b/src/tools/rustfmt/appveyor.yml
deleted file mode 100644 (file)
index b3dda09..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-environment:
-  global:
-    PROJECT_NAME: rustfmt
-
-build: false
-
-test_script:
-  - echo Why does no one have access to delete me?
index 7aea6222b8bc5f7a8168857e36b7b501b225b267..6a711c0171aebb99078b65ccb5a70629e7338629 100644 (file)
@@ -3,19 +3,28 @@
 ## Installation
 
 - Install [CLion](https://www.jetbrains.com/clion/), [IntelliJ Ultimate or CE](https://www.jetbrains.com/idea/) through the direct download link or using the [JetBrains Toolbox](https://www.jetbrains.com/toolbox/).
-  CLion provides a built-in debugger interface but its not free like IntelliJ CE - which does not provide the debugger interface. (IntelliJ seems to lack the toolchain for that, see this discussion [intellij-rust/issues/535](https://github.com/intellij-rust/intellij-rust/issues/535))
-  
-- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File -> Settings -> Plugins and press "Install JetBrains Plugin"
-  ![plugins](https://user-images.githubusercontent.com/1133787/47240861-f40af680-d3e9-11e8-9b82-cdd5c8d5f5b8.png)
+  CLion and IntelliJ Ultimate [provide a built-in debugger interface](https://github.com/intellij-rust/intellij-rust#compatible-ides) but they are not free like IntelliJ CE.
+
+- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File → Settings → Plugins and searching the plugin in the Marketplace
+  ![plugins](https://user-images.githubusercontent.com/6505554/83944518-6f1e5c00-a81d-11ea-9c35-e16948811ba8.png)
 
-- Press "Install" on the rust plugin
-  ![install rust](https://user-images.githubusercontent.com/1133787/47240803-c0c86780-d3e9-11e8-9265-22f735e4d7ed.png)
+- Press "Install" on the Rust plugin
+  ![install rust](https://user-images.githubusercontent.com/6505554/83944533-82c9c280-a81d-11ea-86b3-ee2e31bc7d12.png)
   
 - Restart CLion/IntelliJ
 
 ## Configuration
 
-- Open the settings window (File -> Settings) and search for "reformat"
+### Run Rustfmt on save
+
+- Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save"
+  ![run_rustfmt_on_save](https://user-images.githubusercontent.com/6505554/83944610-3468f380-a81e-11ea-9c34-0cbd18dd4969.png)
+
+- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually
+
+### Bind shortcut to "Reformat File with Rustfmt" action
+
+- Open the settings window (File → Settings) and search for "reformat"
   ![keymap](https://user-images.githubusercontent.com/1133787/47240922-2ae10c80-d3ea-11e8-9d8f-c798d9749240.png)
 - Right-click on "Reformat File with Rustfmt" and assign a keyboard shortcut
 
diff --git a/src/tools/rustfmt/legacy-rustfmt.toml b/src/tools/rustfmt/legacy-rustfmt.toml
deleted file mode 100644 (file)
index f976fa6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-indent_style = "Visual"
-combine_control_expr = false
index b19ecbdb07c4f425540264a618144618e7acbcab..1d2cad6675117d567194ef4e77cb521abdac7946 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-10-20"
+channel = "nightly-2021-11-08"
 components = ["rustc-dev"]
index a5982820e3ded6f2de868975ac9003ee441623f4..76b66e9da80980ea30f24aa585ac64caea4ef71c 100644 (file)
@@ -451,7 +451,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                         if next.is_doc_comment() {
                             let snippet = context.snippet(missing_span);
                             let (_, mlb) = has_newlines_before_after_comment(snippet);
-                            result.push_str(&mlb);
+                            result.push_str(mlb);
                         }
                     }
                     result.push('\n');
@@ -484,7 +484,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     if next.is_doc_comment() {
                         let snippet = context.snippet(missing_span);
                         let (_, mlb) = has_newlines_before_after_comment(snippet);
-                        result.push_str(&mlb);
+                        result.push_str(mlb);
                     }
                 }
                 result.push('\n');
index c3dcb84c9488d53b001f5febb9c8803039f9a27c..f653a12a8afeb95fb22d3c42475c14ca8da3947e 100644 (file)
@@ -77,7 +77,7 @@ fn test_doc_comment_is_formatted_correctly(
     ) {
         assert_eq!(
             expected_comment,
-            format!("{}", DocCommentFormatter::new(&literal, style))
+            format!("{}", DocCommentFormatter::new(literal, style))
         );
     }
 }
index 1bcc5c0dada3bd0695d9fd5c8167890ab7eff255..9d2e97c9479fc2dda6c063467b4cbde52a934b4b 100644 (file)
@@ -20,7 +20,7 @@
 };
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
     let opts = make_opts();
 
     let exit_code = match execute(&opts) {
index 1d423ac34919b421a31e4f77f4e63030746082a6..759b21218c353e70787f853a6c09725bf7132b10 100644 (file)
@@ -401,12 +401,12 @@ fn get_targets_root_only(
 
 fn get_targets_recursive(
     manifest_path: Option<&Path>,
-    mut targets: &mut BTreeSet<Target>,
+    targets: &mut BTreeSet<Target>,
     visited: &mut BTreeSet<String>,
 ) -> Result<(), io::Error> {
     let metadata = get_cargo_metadata(manifest_path)?;
     for package in &metadata.packages {
-        add_targets(&package.targets, &mut targets);
+        add_targets(&package.targets, targets);
 
         // Look for local dependencies using information available since cargo v1.51
         // It's theoretically possible someone could use a newer version of rustfmt with
@@ -427,7 +427,7 @@ fn get_targets_recursive(
                     .any(|p| p.manifest_path.eq(&manifest_path))
             {
                 visited.insert(dependency.name.to_owned());
-                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
+                get_targets_recursive(Some(&manifest_path), targets, visited)?;
             }
         }
     }
index 614638ea2abfbea7c4096c9cf5443bb7afe17041..e26e24ec55ad6c40fe495ddc41c57cba89e218c5 100644 (file)
@@ -568,7 +568,7 @@ fn format_last_child(
         } else {
             self.rewrites
                 .iter()
-                .map(|rw| utils::unicode_str_width(&rw))
+                .map(|rw| utils::unicode_str_width(rw))
                 .sum()
         } + last.tries;
         let one_line_budget = if self.child_count == 1 {
@@ -673,7 +673,7 @@ fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Opt
                 ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector),
                 _ => result.push_str(&connector),
             }
-            result.push_str(&rewrite);
+            result.push_str(rewrite);
         }
 
         Some(result)
index dc4f4516252b122267dfb3030bdc01324deeba3a..7b76c232937dc7cea63d7df07716777730cbeef2 100644 (file)
@@ -405,7 +405,7 @@ impl CodeBlockAttribute {
     /// attributes are valid rust attributes
     /// See <https://doc.rust-lang.org/rustdoc/print.html#attributes>
     fn new(attributes: &str) -> CodeBlockAttribute {
-        for attribute in attributes.split(",") {
+        for attribute in attributes.split(',') {
             match attribute.trim() {
                 "" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018"
                 | "edition2021" => (),
@@ -563,7 +563,7 @@ fn join_block(s: &str, sep: &str) -> String {
             result.push_str(line);
             result.push_str(match iter.peek() {
                 Some(next_line) if next_line.is_empty() => sep.trim_end(),
-                Some(..) => &sep,
+                Some(..) => sep,
                 None => "",
             });
         }
@@ -622,7 +622,7 @@ fn handle_line(
         let is_last = i == count_newlines(orig);
 
         if let Some(ref mut ib) = self.item_block {
-            if ib.add_line(&line) {
+            if ib.add_line(line) {
                 return false;
             }
             self.is_prev_line_multi_line = false;
@@ -684,8 +684,8 @@ fn handle_line(
         self.item_block = None;
         if let Some(stripped) = line.strip_prefix("```") {
             self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
-        } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) {
-            let ib = ItemizedBlock::new(&line);
+        } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(line) {
+            let ib = ItemizedBlock::new(line);
             self.item_block = Some(ib);
             return false;
         }
@@ -941,7 +941,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s
     {
         (&line[4..], true)
     } else if let CommentStyle::Custom(opener) = *style {
-        if let Some(ref stripped) = line.strip_prefix(opener) {
+        if let Some(stripped) = line.strip_prefix(opener) {
             (stripped, true)
         } else {
             (&line[opener.trim_end().len()..], false)
@@ -1384,7 +1384,7 @@ fn next(&mut self) -> Option<Self::Item> {
             None => unreachable!(),
         };
 
-        while let Some((kind, c)) = self.base.next() {
+        for (kind, c) in self.base.by_ref() {
             // needed to set the kind of the ending character on the last line
             self.kind = kind;
             if c == '\n' {
@@ -1570,7 +1570,7 @@ pub(crate) fn recover_comment_removed(
                 context.parse_sess.span_to_filename(span),
                 vec![FormattingError::from_span(
                     span,
-                    &context.parse_sess,
+                    context.parse_sess,
                     ErrorKind::LostComment,
                 )],
             );
@@ -1675,7 +1675,7 @@ fn next(&mut self) -> Option<Self::Item> {
 fn remove_comment_header(comment: &str) -> &str {
     if comment.starts_with("///") || comment.starts_with("//!") {
         &comment[3..]
-    } else if let Some(ref stripped) = comment.strip_prefix("//") {
+    } else if let Some(stripped) = comment.strip_prefix("//") {
         stripped
     } else if (comment.starts_with("/**") && !comment.starts_with("/**/"))
         || comment.starts_with("/*!")
index e92f8e8a53152e666cec884eae3a8808bcf40d18..bce9e5d07f267a67a8c39917609d4fa38cfbf115 100644 (file)
@@ -20,7 +20,7 @@ pub enum NewlineStyle {
     Windows,
     /// Force CR (`\n).
     Unix,
-    /// `\r\n` in Windows, `\n`` on other platforms.
+    /// `\r\n` in Windows, `\n` on other platforms.
     Native,
 }
 
@@ -112,6 +112,8 @@ pub enum GroupImportsTactic {
     ///  2. other imports
     ///  3. `self` / `crate` / `super` imports
     StdExternalCrate,
+    /// Discard existing groups, and create a single group for everything
+    One,
 }
 
 #[config_type]
index 4448214f3ff2cd1ac4c2fd7e519ca8342c436289..76f2527db3dad1d69c78d8b54c7eeea4244b4469 100644 (file)
@@ -121,7 +121,7 @@ fn emits_single_xml_tree_containing_all_files() {
             format!(r#"<file name="{}">"#, bin_file),
             format!(
                 r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
-                XmlEscaped(&r#"    println!("Hello, world!");"#),
+                XmlEscaped(r#"    println!("Hello, world!");"#),
             ),
             String::from("</file>"),
         ];
@@ -129,7 +129,7 @@ fn emits_single_xml_tree_containing_all_files() {
             format!(r#"<file name="{}">"#, lib_file),
             format!(
                 r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
-                XmlEscaped(&r#"    println!("Greetings!");"#),
+                XmlEscaped(r#"    println!("Greetings!");"#),
             ),
             String::from("</file>"),
         ];
index 2fbbfedb566d13cbe1bb657685de4cd1fa6cd71e..7264ad8bbf365baaf0f2d7e74ff3fb8e61bd5e7d 100644 (file)
@@ -23,7 +23,7 @@ fn emit_formatted_file(
         }: FormattedFile<'_>,
     ) -> Result<EmitterResult, io::Error> {
         const CONTEXT_SIZE: usize = 3;
-        let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE);
+        let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
         let has_diff = !mismatch.is_empty();
 
         if has_diff {
index 7f1dd363f9379a3bd971dbf87c93e4a0955a0cab..58942e442de05ba39ef3472bbb6b51850711ebfc 100644 (file)
@@ -257,7 +257,7 @@ fn needs_space_before_range(context: &RewriteContext<'_>, lhs: &ast::Expr) -> bo
                         }
                         _ => false,
                     },
-                    ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, &expr),
+                    ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr),
                     _ => false,
                 }
             }
@@ -423,7 +423,7 @@ fn rewrite_empty_block(
     prefix: &str,
     shape: Shape,
 ) -> Option<String> {
-    if block_has_statements(&block) {
+    if block_has_statements(block) {
         return None;
     }
 
@@ -1148,7 +1148,7 @@ pub(crate) fn is_empty_block(
     block: &ast::Block,
     attrs: Option<&[ast::Attribute]>,
 ) -> bool {
-    !block_has_statements(&block)
+    !block_has_statements(block)
         && !block_contains_comment(context, block)
         && attrs.map_or(true, |a| inner_attributes(a).is_empty())
 }
@@ -1207,11 +1207,11 @@ fn rewrite_int_lit(context: &RewriteContext<'_>, lit: &ast::Lit, shape: Shape) -
     let span = lit.span;
     let symbol = lit.token.symbol.as_str();
 
-    if symbol.starts_with("0x") {
+    if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
         let hex_lit = match context.config.hex_literal_case() {
             HexLiteralCase::Preserve => None,
-            HexLiteralCase::Upper => Some(symbol[2..].to_ascii_uppercase()),
-            HexLiteralCase::Lower => Some(symbol[2..].to_ascii_lowercase()),
+            HexLiteralCase::Upper => Some(symbol_stripped.to_ascii_uppercase()),
+            HexLiteralCase::Lower => Some(symbol_stripped.to_ascii_lowercase()),
         };
         if let Some(hex_lit) = hex_lit {
             return wrap_str(
@@ -1621,7 +1621,7 @@ enum StructLitField<'a> {
     };
 
     let fields_str =
-        wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?;
+        wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
     Some(format!("{} {{{}}}", path_str, fields_str))
 
     // FIXME if context.config.indent_style() == Visual, but we run out
@@ -1888,7 +1888,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
     shape: Shape,
     rhs_tactics: RhsTactics,
 ) -> Option<String> {
-    let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') {
+    let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
         shape.indent.width()
     } else {
         0
@@ -1947,7 +1947,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
 
     if contains_comment {
         let rhs = rhs.trim_start();
-        combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend)
+        combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend)
     } else {
         Some(lhs + &rhs)
     }
@@ -1962,6 +1962,9 @@ fn choose_rhs<R: Rewrite>(
     has_rhs_comment: bool,
 ) -> Option<String> {
     match orig_rhs {
+        Some(ref new_str) if new_str.is_empty() => {
+            return Some(String::new());
+        }
         Some(ref new_str)
             if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
         {
index c751932273b0a8f27c494f25799a49a9dfc08f33..655aeda42bf28daab91e885b1fae84f37e355b14 100644 (file)
@@ -64,7 +64,7 @@ pub struct Opts {
 }
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
     let opts = Opts::from_args();
     if let Err(e) = run(opts) {
         println!("{}", e);
index 9ef47b887cadb8809345b1dc196017bbbad92c59..7d0facb8f12cf683b93fe7e17f630ce488190652 100644 (file)
@@ -155,7 +155,7 @@ fn format_file(
         let snippet_provider = self.parse_session.snippet_provider(module.span);
         let mut visitor = FmtVisitor::from_parse_sess(
             &self.parse_session,
-            &self.config,
+            self.config,
             &snippet_provider,
             self.report.clone(),
         );
@@ -180,7 +180,7 @@ fn format_file(
             &mut visitor.buffer,
             &path,
             &visitor.skipped_range.borrow(),
-            &self.config,
+            self.config,
             &self.report,
         );
 
index 16f5d1dd4f234fe17091843ebcfa8133bacffaaa..579778edbe742704519998bd1aba4d1fd1bdf95d 100644 (file)
@@ -170,7 +170,7 @@ fn from_args(matches: &Matches, opts: &Options) -> Config {
 }
 
 fn main() {
-    env_logger::init();
+    env_logger::Builder::from_env("RUSTFMT_LOG").init();
 
     let opts = make_opts();
     let matches = opts
index 5ac799366894de843dd6250a97adc2786a1cc1e4..40e0d06f99df8d14b7279dabb7bf503c747a6fcc 100644 (file)
@@ -275,7 +275,7 @@ pub(crate) fn rewrite_top_level(
         shape: Shape,
     ) -> Option<String> {
         let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| {
-            crate::utils::format_visibility(context, &vis)
+            crate::utils::format_visibility(context, vis)
         });
         let use_str = self
             .rewrite(context, shape.offset_left(vis.len())?)
@@ -929,7 +929,7 @@ impl Rewrite for UseTree {
     fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
         let mut result = String::with_capacity(256);
         let mut iter = self.path.iter().peekable();
-        while let Some(ref segment) = iter.next() {
+        while let Some(segment) = iter.next() {
             let segment_str = segment.rewrite(context, shape)?;
             result.push_str(&segment_str);
             if iter.peek().is_some() {
index 1cb1a2701c36bf24f78109c56c45d320c4da2806..50121a8b6b50e7d506d07e9a14ed645579e2d094 100644 (file)
@@ -226,7 +226,7 @@ pub(crate) fn from_fn_kind(
     fn to_str(&self, context: &RewriteContext<'_>) -> String {
         let mut result = String::with_capacity(128);
         // Vis defaultness constness unsafety abi.
-        result.push_str(&*format_visibility(context, &self.visibility));
+        result.push_str(&*format_visibility(context, self.visibility));
         result.push_str(format_defaultness(self.defaultness));
         result.push_str(format_constness(self.constness));
         result.push_str(format_async(&self.is_async));
@@ -622,7 +622,7 @@ fn both_opaque(
             fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
                 match (a, b) {
                     (TyAlias(lty), TyAlias(rty))
-                        if both_type(&lty.3, &rty.3) || both_opaque(&lty.3, &rty.3) =>
+                        if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
                     {
                         false
                     }
@@ -633,7 +633,7 @@ fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
 
             buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) {
                 (TyAlias(lty), TyAlias(rty))
-                    if both_type(&lty.3, &rty.3) || both_opaque(&lty.3, &rty.3) =>
+                    if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
                 {
                     a.ident.as_str().cmp(&b.ident.as_str())
                 }
@@ -641,8 +641,8 @@ fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
                     a.ident.as_str().cmp(&b.ident.as_str())
                 }
                 (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()),
-                (TyAlias(ty), _) if is_type(&ty.3) => Ordering::Less,
-                (_, TyAlias(ty)) if is_type(&ty.3) => Ordering::Greater,
+                (TyAlias(ty), _) if is_type(&ty.ty) => Ordering::Less,
+                (_, TyAlias(ty)) if is_type(&ty.ty) => Ordering::Greater,
                 (TyAlias(..), _) => Ordering::Less,
                 (_, TyAlias(..)) => Ordering::Greater,
                 (Const(..), _) => Ordering::Less,
@@ -679,7 +679,7 @@ pub(crate) fn format_impl(
     offset: Indent,
 ) -> Option<String> {
     if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::ImplKind {
+        let ast::Impl {
             ref generics,
             ref self_ty,
             ref items,
@@ -833,7 +833,7 @@ fn format_impl_ref_and_type(
     offset: Indent,
 ) -> Option<String> {
     if let ast::ItemKind::Impl(impl_kind) = &item.kind {
-        let ast::ImplKind {
+        let ast::Impl {
             unsafety,
             polarity,
             defaultness,
@@ -1029,8 +1029,13 @@ pub(crate) fn format_trait(
     offset: Indent,
 ) -> Option<String> {
     if let ast::ItemKind::Trait(trait_kind) = &item.kind {
-        let ast::TraitKind(is_auto, unsafety, ref generics, ref generic_bounds, ref trait_items) =
-            **trait_kind;
+        let ast::Trait {
+            is_auto,
+            unsafety,
+            ref generics,
+            ref bounds,
+            ref items,
+        } = **trait_kind;
         let mut result = String::with_capacity(128);
         let header = format!(
             "{}{}{}trait ",
@@ -1048,11 +1053,11 @@ pub(crate) fn format_trait(
         result.push_str(&generics_str);
 
         // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
-        if !generic_bounds.is_empty() {
+        if !bounds.is_empty() {
             let ident_hi = context
                 .snippet_provider
                 .span_after(item.span, &item.ident.as_str());
-            let bound_hi = generic_bounds.last().unwrap().span().hi();
+            let bound_hi = bounds.last().unwrap().span().hi();
             let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
             if contains_comment(snippet) {
                 return None;
@@ -1061,7 +1066,7 @@ pub(crate) fn format_trait(
             result = rewrite_assign_rhs_with(
                 context,
                 result + ":",
-                generic_bounds,
+                bounds,
                 shape,
                 RhsTactics::ForceNextLineWithoutIndent,
             )?;
@@ -1072,10 +1077,10 @@ pub(crate) fn format_trait(
             let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
 
             let where_budget = context.budget(last_line_width(&result));
-            let pos_before_where = if generic_bounds.is_empty() {
+            let pos_before_where = if bounds.is_empty() {
                 generics.where_clause.span.lo()
             } else {
-                generic_bounds[generic_bounds.len() - 1].span().hi()
+                bounds[bounds.len() - 1].span().hi()
             };
             let option = WhereClauseOption::snuggled(&generics_str);
             let where_clause_str = rewrite_where_clause(
@@ -1122,19 +1127,31 @@ pub(crate) fn format_trait(
             }
         }
 
+        let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
+        let snippet = context.snippet(block_span);
+        let open_pos = snippet.find_uncommented("{")? + 1;
+
         match context.config.brace_style() {
             _ if last_line_contains_single_line_comment(&result)
                 || last_line_width(&result) + 2 > context.budget(offset.width()) =>
             {
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
+            _ if context.config.empty_item_single_line()
+                && items.is_empty()
+                && !result.contains('\n')
+                && !contains_comment(&snippet[open_pos..]) =>
+            {
+                result.push_str(" {}");
+                return Some(result);
+            }
             BraceStyle::AlwaysNextLine => {
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
             BraceStyle::PreferSameLine => result.push(' '),
             BraceStyle::SameLineWhere => {
                 if result.contains('\n')
-                    || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty())
+                    || (!generics.where_clause.predicates.is_empty() && !items.is_empty())
                 {
                     result.push_str(&offset.to_string_with_newline(context.config));
                 } else {
@@ -1144,17 +1161,14 @@ pub(crate) fn format_trait(
         }
         result.push('{');
 
-        let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
-        let snippet = context.snippet(block_span);
-        let open_pos = snippet.find_uncommented("{")? + 1;
         let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
 
-        if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
+        if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
             let mut visitor = FmtVisitor::from_context(context);
             visitor.block_indent = offset.block_only().block_indent(context.config);
             visitor.last_pos = block_span.lo() + BytePos(open_pos as u32);
 
-            for item in trait_items {
+            for item in items {
                 visitor.visit_trait_item(item);
             }
 
@@ -1176,18 +1190,6 @@ pub(crate) fn format_trait(
     }
 }
 
-struct OpaqueTypeBounds<'a> {
-    generic_bounds: &'a ast::GenericBounds,
-}
-
-impl<'a> Rewrite for OpaqueTypeBounds<'a> {
-    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        self.generic_bounds
-            .rewrite(context, shape)
-            .map(|s| format!("impl {}", s))
-    }
-}
-
 pub(crate) struct TraitAliasBounds<'a> {
     generic_bounds: &'a ast::GenericBounds,
     generics: &'a ast::Generics,
@@ -1220,7 +1222,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
         } else if fits_single_line {
             Cow::from(" ")
         } else {
-            shape.indent.to_string_with_newline(&context.config)
+            shape.indent.to_string_with_newline(context.config)
         };
 
         Some(format!("{}{}{}", generic_bounds_str, space, where_str))
@@ -1238,7 +1240,7 @@ pub(crate) fn format_trait_alias(
     let alias = rewrite_ident(context, ident);
     // 6 = "trait ", 2 = " ="
     let g_shape = shape.offset_left(6)?.sub_width(2)?;
-    let generics_str = rewrite_generics(context, &alias, generics, g_shape)?;
+    let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
     let vis_str = format_visibility(context, vis);
     let lhs = format!("{}trait {} =", vis_str, generics_str);
     // 1 = ";"
@@ -1386,7 +1388,7 @@ fn format_empty_struct_or_tuple(
     closer: &str,
 ) {
     // 3 = " {}" or "();"
-    let used_width = last_line_used_width(&result, offset.width()) + 3;
+    let used_width = last_line_used_width(result, offset.width()) + 3;
     if used_width > context.config.max_width() {
         result.push_str(&offset.to_string_with_newline(context.config))
     }
@@ -1509,17 +1511,84 @@ fn format_tuple_struct(
     Some(result)
 }
 
-pub(crate) fn rewrite_type<R: Rewrite>(
-    context: &RewriteContext<'_>,
+pub(crate) enum ItemVisitorKind<'a> {
+    Item(&'a ast::Item),
+    AssocTraitItem(&'a ast::AssocItem),
+    AssocImplItem(&'a ast::AssocItem),
+    ForeignItem(&'a ast::ForeignItem),
+}
+
+struct TyAliasRewriteInfo<'c, 'g>(
+    &'c RewriteContext<'c>,
+    Indent,
+    &'g ast::Generics,
+    symbol::Ident,
+    Span,
+);
+
+pub(crate) fn rewrite_type_alias<'a, 'b>(
+    ty_alias_kind: &ast::TyAlias,
+    context: &RewriteContext<'a>,
     indent: Indent,
-    ident: symbol::Ident,
-    vis: &ast::Visibility,
-    generics: &ast::Generics,
+    visitor_kind: &ItemVisitorKind<'b>,
+    span: Span,
+) -> Option<String> {
+    use ItemVisitorKind::*;
+
+    let ast::TyAlias {
+        defaultness,
+        ref generics,
+        ref bounds,
+        ref ty,
+    } = *ty_alias_kind;
+    let ty_opt = ty.as_ref().map(|t| &**t);
+    let (ident, vis) = match visitor_kind {
+        Item(i) => (i.ident, &i.vis),
+        AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
+        ForeignItem(i) => (i.ident, &i.vis),
+    };
+    let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span);
+
+    // Type Aliases are formatted slightly differently depending on the context
+    // in which they appear, whether they are opaque, and whether they are associated.
+    // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
+    // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
+    match (visitor_kind, ty_opt) {
+        (Item(_), None) => {
+            let op_ty = OpaqueType { bounds };
+            rewrite_ty(rw_info, Some(bounds), Some(&op_ty), vis)
+        }
+        (Item(_), Some(ty)) => rewrite_ty(rw_info, Some(bounds), Some(&*ty), vis),
+        (AssocImplItem(_), _) => {
+            let result = if let Some(ast::Ty {
+                kind: ast::TyKind::ImplTrait(_, ref bounds),
+                ..
+            }) = ty_opt
+            {
+                let op_ty = OpaqueType { bounds };
+                rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY)
+            } else {
+                rewrite_ty(rw_info, None, ty.as_ref(), vis)
+            }?;
+            match defaultness {
+                ast::Defaultness::Default(..) => Some(format!("default {}", result)),
+                _ => Some(result),
+            }
+        }
+        (AssocTraitItem(_), _) | (ForeignItem(_), _) => {
+            rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis)
+        }
+    }
+}
+
+fn rewrite_ty<R: Rewrite>(
+    rw_info: &TyAliasRewriteInfo<'_, '_>,
     generic_bounds_opt: Option<&ast::GenericBounds>,
     rhs: Option<&R>,
-    span: Span,
+    vis: &ast::Visibility,
 ) -> Option<String> {
     let mut result = String::with_capacity(128);
+    let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info;
     result.push_str(&format!("{}type ", format_visibility(context, vis)));
     let ident_str = rewrite_ident(context, ident);
 
@@ -1607,28 +1676,6 @@ pub(crate) fn rewrite_type<R: Rewrite>(
     }
 }
 
-pub(crate) fn rewrite_opaque_type(
-    context: &RewriteContext<'_>,
-    indent: Indent,
-    ident: symbol::Ident,
-    generic_bounds: &ast::GenericBounds,
-    generics: &ast::Generics,
-    vis: &ast::Visibility,
-    span: Span,
-) -> Option<String> {
-    let opaque_type_bounds = OpaqueTypeBounds { generic_bounds };
-    rewrite_type(
-        context,
-        indent,
-        ident,
-        vis,
-        generics,
-        Some(generic_bounds),
-        Some(&opaque_type_bounds),
-        span,
-    )
-}
-
 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
     (
         if config.space_before_colon() { " " } else { "" },
@@ -1866,42 +1913,6 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
     }
 }
 
-pub(crate) fn rewrite_impl_type(
-    ident: symbol::Ident,
-    vis: &ast::Visibility,
-    defaultness: ast::Defaultness,
-    ty_opt: Option<&ptr::P<ast::Ty>>,
-    generics: &ast::Generics,
-    context: &RewriteContext<'_>,
-    indent: Indent,
-    span: Span,
-) -> Option<String> {
-    // Opaque type
-    let result = if let Some(rustc_ast::ast::Ty {
-        kind: ast::TyKind::ImplTrait(_, ref bounds),
-        ..
-    }) = ty_opt.map(|t| &**t)
-    {
-        rewrite_type(
-            context,
-            indent,
-            ident,
-            &DEFAULT_VISIBILITY,
-            generics,
-            None,
-            Some(&OpaqueType { bounds }),
-            span,
-        )
-    } else {
-        rewrite_type(context, indent, ident, vis, generics, None, ty_opt, span)
-    }?;
-
-    match defaultness {
-        ast::Defaultness::Default(..) => Some(format!("default {}", result)),
-        _ => Some(result),
-    }
-}
-
 impl Rewrite for ast::FnRetTy {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         match *self {
@@ -2066,7 +2077,7 @@ fn rewrite_explicit_self(
                     )?;
                     Some(combine_strs_with_missing_comments(
                         context,
-                        &param_attrs,
+                        param_attrs,
                         &format!("&{} {}self", lifetime_str, mut_str),
                         span,
                         shape,
@@ -2075,7 +2086,7 @@ fn rewrite_explicit_self(
                 }
                 None => Some(combine_strs_with_missing_comments(
                     context,
-                    &param_attrs,
+                    param_attrs,
                     &format!("&{}self", mut_str),
                     span,
                     shape,
@@ -2091,7 +2102,7 @@ fn rewrite_explicit_self(
 
             Some(combine_strs_with_missing_comments(
                 context,
-                &param_attrs,
+                param_attrs,
                 &format!("{}self: {}", format_mutability(mutability), type_str),
                 span,
                 shape,
@@ -2100,7 +2111,7 @@ fn rewrite_explicit_self(
         }
         ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments(
             context,
-            &param_attrs,
+            param_attrs,
             &format!("{}self", format_mutability(mutability)),
             span,
             shape,
@@ -2226,7 +2237,7 @@ fn rewrite_fn_base(
     }
 
     // Skip `pub(crate)`.
-    let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
+    let lo_after_visibility = get_bytepos_after_visibility(fn_sig.visibility, span);
     // A conservative estimation, the goal is to be over all parens in generics
     let params_start = fn_sig
         .generics
@@ -2984,7 +2995,7 @@ fn format_header(
     let mut result = String::with_capacity(128);
     let shape = Shape::indented(offset, context.config);
 
-    result.push_str(&format_visibility(context, vis).trim());
+    result.push_str(format_visibility(context, vis).trim());
 
     // Check for a missing comment between the visibility and the item name.
     let after_vis = vis.span.hi();
@@ -3005,7 +3016,7 @@ fn format_header(
         }
     }
 
-    result.push_str(&rewrite_ident(context, ident));
+    result.push_str(rewrite_ident(context, ident));
 
     result
 }
@@ -3125,17 +3136,22 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
 
         let item_str = match self.kind {
             ast::ForeignItemKind::Fn(ref fn_kind) => {
-                let ast::FnKind(defaultness, ref fn_sig, ref generics, ref block) = **fn_kind;
-                if let Some(ref body) = block {
+                let ast::Fn {
+                    defaultness,
+                    ref sig,
+                    ref generics,
+                    ref body,
+                } = **fn_kind;
+                if let Some(ref body) = body {
                     let mut visitor = FmtVisitor::from_context(context);
                     visitor.block_indent = shape.indent;
                     visitor.last_pos = self.span.lo();
                     let inner_attrs = inner_attributes(&self.attrs);
                     let fn_ctxt = visit::FnCtxt::Foreign;
                     visitor.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, self.ident, &sig, &self.vis, Some(body)),
                         generics,
-                        &fn_sig.decl,
+                        &sig.decl,
                         self.span,
                         defaultness,
                         Some(&inner_attrs),
@@ -3146,7 +3162,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                         context,
                         shape.indent,
                         self.ident,
-                        &FnSig::from_method_sig(&fn_sig, generics, &self.vis),
+                        &FnSig::from_method_sig(&sig, generics, &self.vis),
                         span,
                         FnBraceStyle::None,
                     )
@@ -3167,19 +3183,9 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                 // 1 = ;
                 rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
             }
-            ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
-                    **ty_alias_kind;
-                rewrite_type(
-                    &context,
-                    shape.indent,
-                    self.ident,
-                    &self.vis,
-                    generics,
-                    Some(generic_bounds),
-                    type_default.as_ref(),
-                    self.span,
-                )
+            ast::ForeignItemKind::TyAlias(ref ty_alias) => {
+                let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
+                rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
             }
             ast::ForeignItemKind::MacCall(ref mac) => {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Item)
@@ -3229,7 +3235,7 @@ fn rewrite_attrs(
     combine_strs_with_missing_comments(
         context,
         &attrs_str,
-        &item_str,
+        item_str,
         missed_span,
         shape,
         allow_extend,
index 47a7b9d4dbe3cb80baa2d08d979e9e94e2b56241..792a1080f0e92189e276168cc0344ef8ba423eba 100644 (file)
@@ -283,7 +283,7 @@ pub fn fancy_print(
         writeln!(
             t,
             "{}",
-            FormatReportFormatterBuilder::new(&self)
+            FormatReportFormatterBuilder::new(self)
                 .enable_colors(true)
                 .build()
         )?;
@@ -297,7 +297,7 @@ pub fn fancy_print(
 impl fmt::Display for FormatReport {
     // Prints all the formatting errors.
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?;
+        write!(fmt, "{}", FormatReportFormatterBuilder::new(self).build())?;
         Ok(())
     }
 }
index c04b4787616933e84528d1695a386eefce5769ab..d341ec8e6b0e7d15f428cc3e91527635129f9687 100644 (file)
@@ -386,7 +386,7 @@ pub(crate) fn write_list<I, T>(items: I, formatting: &ListFormatting<'_>) -> Opt
                         result.push('\n');
                         result.push_str(indent_str);
                         // This is the width of the item (without comments).
-                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
+                        line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(s));
                     }
                 } else {
                     result.push(' ')
@@ -820,7 +820,7 @@ fn calculate_width<I, T>(items: I) -> (usize, usize)
 pub(crate) fn total_item_width(item: &ListItem) -> usize {
     comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..]))
         + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..]))
-        + item.item.as_ref().map_or(0, |s| unicode_str_width(&s))
+        + item.item.as_ref().map_or(0, |s| unicode_str_width(s))
 }
 
 fn comment_len(comment: Option<&str>) -> usize {
index 927187dfd8a2336b20220dd9e794bc04171f0eff..ef747638e33ec83459e4b9f9fe02d052e41c4812 100644 (file)
@@ -186,7 +186,7 @@ fn return_macro_parse_failure_fallback(
         })
         .unwrap_or(false);
     if is_like_block_indent_style {
-        return trim_left_preserve_layout(context.snippet(span), indent, &context.config);
+        return trim_left_preserve_layout(context.snippet(span), indent, context.config);
     }
 
     context.skipped_range.borrow_mut().push((
@@ -437,7 +437,7 @@ fn rewrite_macro_inner(
             // the `macro_name!` and `{ /* macro_body */ }` but skip modifying
             // anything in between the braces (for now).
             let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
-            match trim_left_preserve_layout(snippet, shape.indent, &context.config) {
+            match trim_left_preserve_layout(snippet, shape.indent, context.config) {
                 Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
                 None => Some(format!("{} {}", macro_name, snippet)),
             }
@@ -901,7 +901,7 @@ fn add_repeat(
                     break;
                 }
                 TokenTree::Token(ref t) => {
-                    buffer.push_str(&pprust::token_to_string(&t));
+                    buffer.push_str(&pprust::token_to_string(t));
                 }
                 _ => return None,
             }
@@ -1045,7 +1045,7 @@ fn wrap_macro_args_inner(
     let mut iter = args.iter().peekable();
     let indent_str = shape.indent.to_string_with_newline(context.config);
 
-    while let Some(ref arg) = iter.next() {
+    while let Some(arg) = iter.next() {
         result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?);
 
         if use_multiple_lines
@@ -1055,7 +1055,7 @@ fn wrap_macro_args_inner(
                 result.pop();
             }
             result.push_str(&indent_str);
-        } else if let Some(ref next_arg) = iter.peek() {
+        } else if let Some(next_arg) = iter.peek() {
             let space_before_dollar =
                 !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar();
             let space_before_brace = next_arg.kind.starts_with_brace();
@@ -1370,7 +1370,7 @@ fn rewrite(
                     {
                         s += &indent_str;
                     }
-                    (s + l + "\n", indent_next_line(kind, &l, &config))
+                    (s + l + "\n", indent_next_line(kind, l, &config))
                 },
             )
             .0;
@@ -1514,11 +1514,11 @@ fn rewrite_macro_with_items(
             MacroArg::Item(item) => item,
             _ => return None,
         };
-        visitor.visit_item(&item);
+        visitor.visit_item(item);
     }
 
     let mut result = String::with_capacity(256);
-    result.push_str(&macro_name);
+    result.push_str(macro_name);
     result.push_str(opener);
     result.push_str(&visitor.block_indent.to_string_with_newline(context.config));
     result.push_str(visitor.buffer.trim());
index 5a6ed0ec06e55a37ca203bafdbd9625a2ad3ce4c..22d23fc1cdba49bc3f1f68fc4247f5f521ceeabd 100644 (file)
@@ -168,7 +168,7 @@ fn collect_beginning_verts(
         .map(|a| {
             context
                 .snippet(a.pat.span)
-                .starts_with("|")
+                .starts_with('|')
                 .then(|| a.pat.span().lo())
         })
         .collect()
@@ -319,7 +319,7 @@ fn flatten_arm_body<'a>(
     let can_extend =
         |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr);
 
-    if let Some(ref block) = block_can_be_flattened(context, body) {
+    if let Some(block) = block_can_be_flattened(context, body) {
         if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
             if let ast::ExprKind::Block(..) = expr.kind {
                 flatten_arm_body(context, expr, None)
@@ -393,7 +393,7 @@ fn rewrite_match_body(
         if comment_str.is_empty() {
             String::new()
         } else {
-            rewrite_comment(comment_str, false, shape, &context.config)?
+            rewrite_comment(comment_str, false, shape, context.config)?
         }
     };
 
@@ -408,8 +408,8 @@ fn rewrite_match_body(
                 result.push_str(&arrow_comment);
             }
             result.push_str(&nested_indent_str);
-            result.push_str(&body_str);
-            result.push_str(&comma);
+            result.push_str(body_str);
+            result.push_str(comma);
             return Some(result);
         }
 
@@ -451,7 +451,7 @@ fn rewrite_match_body(
             result.push_str(&arrow_comment);
         }
         result.push_str(&block_sep);
-        result.push_str(&body_str);
+        result.push_str(body_str);
         result.push_str(&body_suffix);
         Some(result)
     };
index ded34d9032f91f188c11c9437b41691cdcce75b5..b1f229d9daaf5f411082f260aa68e358de077dc9 100644 (file)
@@ -16,7 +16,7 @@
     Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
 };
 use crate::syntux::session::ParseSess;
-use crate::utils::contains_skip;
+use crate::utils::{contains_skip, mk_sp};
 
 mod visitor;
 
@@ -135,10 +135,12 @@ pub(crate) fn visit_crate(
             self.visit_mod_from_ast(&krate.items)?;
         }
 
+        let snippet_provider = self.parse_sess.snippet_provider(krate.span);
+
         self.file_map.insert(
             root_filename,
             Module::new(
-                krate.span,
+                mk_sp(snippet_provider.start_pos(), snippet_provider.end_pos()),
                 None,
                 Cow::Borrowed(&krate.items),
                 Cow::Borrowed(&krate.attrs),
@@ -197,7 +199,7 @@ fn visit_mod_outside_ast(
     /// Visit modules from AST.
     fn visit_mod_from_ast(
         &mut self,
-        items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>,
+        items: &'ast [rustc_ast::ptr::P<ast::Item>],
     ) -> Result<(), ModuleResolutionError> {
         for item in items {
             if is_cfg_if(item) {
@@ -290,7 +292,7 @@ fn visit_sub_mod_inner(
                 };
                 self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
             }
-            SubModKind::Internal(ref item) => {
+            SubModKind::Internal(item) => {
                 self.push_inline_mod_directory(item.ident, &item.attrs);
                 self.visit_sub_mod_after_directory_update(sub_mod, None)
             }
@@ -317,9 +319,11 @@ fn visit_sub_mod_after_directory_update(
         }
         match (sub_mod.ast_mod_kind, sub_mod.items) {
             (Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
-                self.visit_mod_from_ast(&items)
+                self.visit_mod_from_ast(items)
+            }
+            (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
+                self.visit_mod_outside_ast(items)
             }
-            (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items),
             (_, _) => Ok(()),
         }
     }
index ac24181c7805258b89c053d6c444a65709f79af6..3475f5c378cd2fbde554e4a79d0c191bf99d0a97 100644 (file)
@@ -394,7 +394,7 @@ fn rewrite_last_item_with_overflow(
     ) -> Option<String> {
         let last_item = self.last_item()?;
         let rewrite = match last_item {
-            OverflowableItem::Expr(ref expr) => {
+            OverflowableItem::Expr(expr) => {
                 match expr.kind {
                     // When overflowing the closure which consists of a single control flow
                     // expression, force to use block if its condition uses multi line.
index 0f3d5e8f878ba7d7f08883e95c40262bf2d8adfa..d1c75126ea4a7fce24a8eede42ecd677df916d3e 100644 (file)
@@ -55,11 +55,11 @@ fn rewrite_pairs_one_line<T: Rewrite>(
 
     for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) {
         if let Some(rewrite) = rewrite {
-            if !is_single_line(&rewrite) || result.len() > shape.width {
+            if !is_single_line(rewrite) || result.len() > shape.width {
                 return None;
             }
 
-            result.push_str(&rewrite);
+            result.push_str(rewrite);
             result.push(' ');
             result.push_str(s);
             result.push(' ');
@@ -94,18 +94,18 @@ fn rewrite_pairs_multiline<T: Rewrite>(
     shape: Shape,
     context: &RewriteContext<'_>,
 ) -> Option<String> {
-    let rhs_offset = shape.rhs_overhead(&context.config);
+    let rhs_offset = shape.rhs_overhead(context.config);
     let nested_shape = (match context.config.indent_style() {
         IndentStyle::Visual => shape.visual_indent(0),
         IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
     })
-    .with_max_width(&context.config)
+    .with_max_width(context.config)
     .sub_width(rhs_offset)?;
 
     let indent_str = nested_shape.indent.to_string_with_newline(context.config);
     let mut result = String::new();
 
-    result.push_str(&list.list[0].1.as_ref()?);
+    result.push_str(list.list[0].1.as_ref()?);
 
     for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) {
         // The following test checks if we should keep two subexprs on the same
@@ -144,7 +144,7 @@ fn rewrite_pairs_multiline<T: Rewrite>(
             }
         }
 
-        result.push_str(&default_rw.as_ref()?);
+        result.push_str(default_rw.as_ref()?);
     }
     Some(result)
 }
@@ -264,12 +264,12 @@ fn flatten(
                 return node.rewrite(context, shape);
             }
             let nested_overhead = sep + 1;
-            let rhs_offset = shape.rhs_overhead(&context.config);
+            let rhs_offset = shape.rhs_overhead(context.config);
             let nested_shape = (match context.config.indent_style() {
                 IndentStyle::Visual => shape.visual_indent(0),
                 IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
             })
-            .with_max_width(&context.config)
+            .with_max_width(context.config)
             .sub_width(rhs_offset)?;
             let default_shape = match context.config.binop_separator() {
                 SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?,
index ba8d8024a9707c34ef31c4eae24665eb99f5f39d..a80d63201f982902a385d4a192273810fef1edce 100644 (file)
@@ -456,11 +456,11 @@ fn rewrite_tuple_pat(
     context: &RewriteContext<'_>,
     shape: Shape,
 ) -> Option<String> {
-    let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect();
-
-    if pat_vec.is_empty() {
+    if pats.is_empty() {
         return Some(format!("{}()", path_str.unwrap_or_default()));
     }
+    let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect();
+
     let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
     let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
     {
@@ -482,7 +482,7 @@ fn rewrite_tuple_pat(
     let path_str = path_str.unwrap_or_default();
 
     overflow::rewrite_with_parens(
-        &context,
+        context,
         &path_str,
         pat_vec.iter(),
         shape,
index 2c58350d4feb6d8e0bf9a3cbfc15d084a0af73a7..0732c8ee70059ca372ff28c0d2445a2394c586e8 100644 (file)
@@ -118,7 +118,9 @@ fn rewrite_reorderable_or_regroupable_items(
             };
 
             let mut regrouped_items = match context.config.group_imports() {
-                GroupImportsTactic::Preserve => vec![normalized_items],
+                GroupImportsTactic::Preserve | GroupImportsTactic::One => {
+                    vec![normalized_items]
+                }
                 GroupImportsTactic::StdExternalCrate => group_imports(normalized_items),
             };
 
index b5fe4335dd33dff97c682f1820ab14acd748dffc..d1bb2f80004aa08461ddf0306bf2285130f80e35 100644 (file)
@@ -112,7 +112,7 @@ pub(crate) fn parse_file_as_module(
         span: Span,
     ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
-            let mut parser = new_parser_from_file(sess.inner(), &path, Some(span));
+            let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
             match parser.parse_mod(&TokenKind::Eof) {
                 Ok(result) => Some(result),
                 Err(mut e) => {
@@ -125,18 +125,12 @@ pub(crate) fn parse_file_as_module(
             }
         }));
         match result {
-            Ok(Some(m)) => {
-                if !sess.has_errors() {
-                    return Ok(m);
-                }
-
-                if sess.can_reset_errors() {
-                    sess.reset_errors();
-                    return Ok(m);
-                }
-                Err(ParserError::ParseError)
+            Ok(Some(m)) if !sess.has_errors() => Ok(m),
+            Ok(Some(m)) if sess.can_reset_errors() => {
+                sess.reset_errors();
+                Ok(m)
             }
-            Ok(None) => Err(ParserError::ParseError),
+            Ok(_) => Err(ParserError::ParseError),
             Err(..) if path.exists() => Err(ParserError::ParseError),
             Err(_) => Err(ParserError::ParsePanicError),
         }
index 946c076d9f2d1fdf388b19156c5c2a7b5ca254e0..cdb4893d443b9b381cde8e4c1d284aee5154ddd4 100644 (file)
@@ -164,7 +164,7 @@ pub(crate) fn is_file_parsed(&self, path: &Path) -> bool {
     }
 
     pub(crate) fn ignore_file(&self, path: &FileName) -> bool {
-        self.ignore_path_set.as_ref().is_match(&path)
+        self.ignore_path_set.as_ref().is_match(path)
     }
 
     pub(crate) fn set_silent_emitter(&mut self) {
index 48d61289a9b8f34a25d89237f5842a1d4245ed29..e2620508c340bad91699e8ebd90b36f2a80f6049 100644 (file)
@@ -535,9 +535,9 @@ fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<Format
 
         debug!("Testing '{}'...", file_name.display());
 
-        match idempotent_check(&file_name, &opt_config) {
+        match idempotent_check(&file_name, opt_config) {
             Ok(ref report) if report.has_warnings() => {
-                print!("{}", FormatReportFormatterBuilder::new(&report).build());
+                print!("{}", FormatReportFormatterBuilder::new(report).build());
                 fails += 1;
             }
             Ok(report) => reports.push(report),
index e0b55e3efb2c4f5714f09abad473ff7b498aaa96..ae4a0d0fccb191003dd5bdc04d2378c1b6707228 100644 (file)
@@ -5,21 +5,39 @@
 
 use crate::{FileName, Input, Session};
 
-#[test]
-fn nested_out_of_line_mods_loaded() {
-    // See also https://github.com/rust-lang/rustfmt/issues/4874
-    let filename = "tests/mod-resolver/issue-4874/main.rs";
-    let input_file = PathBuf::from(filename);
+fn verify_mod_resolution(input_file_name: &str, exp_misformatted_files: &[&str]) {
+    let input_file = PathBuf::from(input_file_name);
     let config = read_config(&input_file);
     let mut session = Session::<io::Stdout>::new(config, None);
     let report = session
-        .format(Input::File(filename.into()))
+        .format(Input::File(input_file_name.into()))
         .expect("Should not have had any execution errors");
     let errors_by_file = &report.internal.borrow().0;
-    assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
-        "tests/mod-resolver/issue-4874/bar/baz.rs",
-    ))));
-    assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
-        "tests/mod-resolver/issue-4874/foo/qux.rs",
-    ))));
+    for exp_file in exp_misformatted_files {
+        assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(exp_file))));
+    }
+}
+
+#[test]
+fn nested_out_of_line_mods_loaded() {
+    // See also https://github.com/rust-lang/rustfmt/issues/4874
+    verify_mod_resolution(
+        "tests/mod-resolver/issue-4874/main.rs",
+        &[
+            "tests/mod-resolver/issue-4874/bar/baz.rs",
+            "tests/mod-resolver/issue-4874/foo/qux.rs",
+        ],
+    );
+}
+
+#[test]
+fn out_of_line_nested_inline_within_out_of_line() {
+    // See also https://github.com/rust-lang/rustfmt/issues/5063
+    verify_mod_resolution(
+        "tests/mod-resolver/issue-5063/main.rs",
+        &[
+            "tests/mod-resolver/issue-5063/foo/bar/baz.rs",
+            "tests/mod-resolver/issue-5063/foo.rs",
+        ],
+    );
 }
index 62c05ba078c56facce55f848d2b4cee53e0a1c78..9ea90c5e46dd87104522dd220558e7127ade7cdb 100644 (file)
@@ -728,7 +728,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     result = combine_strs_with_missing_comments(
                         context,
                         result.trim_end(),
-                        &mt.ty.rewrite(&context, shape)?,
+                        &mt.ty.rewrite(context, shape)?,
                         before_ty_span,
                         shape,
                         true,
@@ -738,7 +738,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                     let budget = shape.width.checked_sub(used_width)?;
                     let ty_str = mt
                         .ty
-                        .rewrite(&context, Shape::legacy(budget, shape.indent + used_width))?;
+                        .rewrite(context, Shape::legacy(budget, shape.indent + used_width))?;
                     result.push_str(&ty_str);
                 }
 
index 29e1e070d41114079921683fea87f7cd62ec941f..3a8713c5bdb01d678f41892a2a149ee8946e8575 100644 (file)
@@ -42,7 +42,7 @@ pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool {
         (
             VisibilityKind::Restricted { path: p, .. },
             VisibilityKind::Restricted { path: q, .. },
-        ) => pprust::path_to_string(&p) == pprust::path_to_string(&q),
+        ) => pprust::path_to_string(p) == pprust::path_to_string(q),
         (VisibilityKind::Public, VisibilityKind::Public)
         | (VisibilityKind::Inherited, VisibilityKind::Inherited)
         | (
@@ -689,7 +689,7 @@ mod test {
     #[test]
     fn test_remove_trailing_white_spaces() {
         let s = "    r#\"\n        test\n    \"#";
-        assert_eq!(remove_trailing_white_spaces(&s), s);
+        assert_eq!(remove_trailing_white_spaces(s), s);
     }
 
     #[test]
@@ -698,7 +698,7 @@ fn test_trim_left_preserve_layout() {
         let config = Config::default();
         let indent = Indent::new(4, 0);
         assert_eq!(
-            trim_left_preserve_layout(&s, indent, &config),
+            trim_left_preserve_layout(s, indent, &config),
             Some("aaa\n    bbb\n    ccc".to_string())
         );
     }
index d854d90b40b6d9d33e7f7ff4917d8c872c97f6a5..527042d098a1c61f7d6252438ea4b97ba741c5d7 100644 (file)
@@ -12,8 +12,7 @@
 use crate::coverage::transform_missing_snippet;
 use crate::items::{
     format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
-    rewrite_impl_type, rewrite_opaque_type, rewrite_type, FnBraceStyle, FnSig, StaticParts,
-    StructParts,
+    rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts,
 };
 use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
 use crate::modules::Module;
@@ -164,7 +163,7 @@ fn visit_stmt(&mut self, stmt: &Stmt<'_>, include_empty_semi: bool) {
                     );
                 } else {
                     let shape = self.shape();
-                    let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape));
+                    let rewrite = self.with_context(|ctx| stmt.rewrite(ctx, shape));
                     self.push_rewrite(stmt.span(), rewrite)
                 }
             }
@@ -273,9 +272,9 @@ fn close_block(&mut self, span: Span, unindent_comment: bool) {
 
         let comment_snippet = self.snippet(span);
 
-        let align_to_right = if unindent_comment && contains_comment(&comment_snippet) {
+        let align_to_right = if unindent_comment && contains_comment(comment_snippet) {
             let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or("");
-            last_line_width(first_lines) > last_line_width(&comment_snippet)
+            last_line_width(first_lines) > last_line_width(comment_snippet)
         } else {
             false
         };
@@ -439,7 +438,7 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
         let filtered_attrs;
         let mut attrs = &item.attrs;
         let skip_context_saved = self.skip_context.clone();
-        self.skip_context.update_with_attrs(&attrs);
+        self.skip_context.update_with_attrs(attrs);
 
         let should_visit_node_again = match item.kind {
             // For use/extern crate items, skip rewriting attributes but check for a skip attribute.
@@ -488,12 +487,12 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
                 ast::ItemKind::Use(ref tree) => self.format_import(item, tree),
                 ast::ItemKind::Impl { .. } => {
                     let block_indent = self.block_indent;
-                    let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent));
+                    let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::Trait(..) => {
                     let block_indent = self.block_indent;
-                    let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent));
+                    let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
                     self.push_rewrite(item.span, rw);
                 }
                 ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
@@ -540,24 +539,22 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
                     self.visit_static(&StaticParts::from_item(item));
                 }
                 ast::ItemKind::Fn(ref fn_kind) => {
-                    let ast::FnKind(defaultness, ref fn_signature, ref generics, ref block) =
-                        **fn_kind;
-                    if let Some(ref body) = block {
+                    let ast::Fn {
+                        defaultness,
+                        ref sig,
+                        ref generics,
+                        ref body,
+                    } = **fn_kind;
+                    if let Some(ref body) = body {
                         let inner_attrs = inner_attributes(&item.attrs);
-                        let fn_ctxt = match fn_signature.header.ext {
+                        let fn_ctxt = match sig.header.ext {
                             ast::Extern::None => visit::FnCtxt::Free,
                             _ => visit::FnCtxt::Foreign,
                         };
                         self.visit_fn(
-                            visit::FnKind::Fn(
-                                fn_ctxt,
-                                item.ident,
-                                &fn_signature,
-                                &item.vis,
-                                Some(body),
-                            ),
+                            visit::FnKind::Fn(fn_ctxt, item.ident, &sig, &item.vis, Some(body)),
                             generics,
-                            &fn_signature.decl,
+                            &sig.decl,
                             item.span,
                             defaultness,
                             Some(&inner_attrs),
@@ -565,46 +562,14 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
                     } else {
                         let indent = self.block_indent;
                         let rewrite = self.rewrite_required_fn(
-                            indent,
-                            item.ident,
-                            &fn_signature,
-                            &item.vis,
-                            generics,
-                            item.span,
+                            indent, item.ident, &sig, &item.vis, generics, item.span,
                         );
                         self.push_rewrite(item.span, rewrite);
                     }
                 }
-                ast::ItemKind::TyAlias(ref alias_kind) => {
-                    let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref ty) =
-                        **alias_kind;
-                    match ty {
-                        Some(ty) => {
-                            let rewrite = rewrite_type(
-                                &self.get_context(),
-                                self.block_indent,
-                                item.ident,
-                                &item.vis,
-                                generics,
-                                Some(generic_bounds),
-                                Some(&*ty),
-                                item.span,
-                            );
-                            self.push_rewrite(item.span, rewrite);
-                        }
-                        None => {
-                            let rewrite = rewrite_opaque_type(
-                                &self.get_context(),
-                                self.block_indent,
-                                item.ident,
-                                generic_bounds,
-                                generics,
-                                &item.vis,
-                                item.span,
-                            );
-                            self.push_rewrite(item.span, rewrite);
-                        }
-                    }
+                ast::ItemKind::TyAlias(ref ty_alias) => {
+                    use ItemVisitorKind::Item;
+                    self.visit_ty_alias_kind(ty_alias, &Item(&item), item.span);
                 }
                 ast::ItemKind::GlobalAsm(..) => {
                     let snippet = Some(self.snippet(item.span).to_owned());
@@ -627,108 +592,86 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) {
         self.skip_context = skip_context_saved;
     }
 
-    pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
-        skip_out_of_file_lines_range_visitor!(self, ti.span);
+    fn visit_ty_alias_kind(
+        &mut self,
+        ty_kind: &ast::TyAlias,
+        visitor_kind: &ItemVisitorKind<'_>,
+        span: Span,
+    ) {
+        let rewrite = rewrite_type_alias(
+            ty_kind,
+            &self.get_context(),
+            self.block_indent,
+            visitor_kind,
+            span,
+        );
+        self.push_rewrite(span, rewrite);
+    }
+
+    fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
+        use ItemVisitorKind::*;
+        // TODO(calebcartwright): Not sure the skip spans are correct
+        let (ai, skip_span, assoc_ctxt) = match visitor_kind {
+            AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
+            AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl),
+            _ => unreachable!(),
+        };
+        skip_out_of_file_lines_range_visitor!(self, ai.span);
 
-        if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span());
+        if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
+            self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span);
             return;
         }
 
         // TODO(calebcartwright): consider enabling box_patterns feature gate
-        match ti.kind {
-            ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)),
-            ast::AssocItemKind::Fn(ref fn_kind) => {
-                let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
-                if let Some(ref body) = block {
-                    let inner_attrs = inner_attributes(&ti.attrs);
-                    let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait);
+        match (&ai.kind, visitor_kind) {
+            (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
+                self.visit_static(&StaticParts::from_trait_item(&ai))
+            }
+            (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
+                self.visit_static(&StaticParts::from_impl_item(&ai))
+            }
+            (ast::AssocItemKind::Fn(ref fn_kind), _) => {
+                let ast::Fn {
+                    defaultness,
+                    ref sig,
+                    ref generics,
+                    ref body,
+                } = **fn_kind;
+                if let Some(ref body) = body {
+                    let inner_attrs = inner_attributes(&ai.attrs);
+                    let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &ti.vis, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)),
                         generics,
                         &sig.decl,
-                        ti.span,
+                        ai.span,
                         defaultness,
                         Some(&inner_attrs),
                     );
                 } else {
                     let indent = self.block_indent;
                     let rewrite =
-                        self.rewrite_required_fn(indent, ti.ident, sig, &ti.vis, generics, ti.span);
-                    self.push_rewrite(ti.span, rewrite);
+                        self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span);
+                    self.push_rewrite(ai.span, rewrite);
                 }
             }
-            ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
-                    **ty_alias_kind;
-                let rewrite = rewrite_type(
-                    &self.get_context(),
-                    self.block_indent,
-                    ti.ident,
-                    &ti.vis,
-                    generics,
-                    Some(generic_bounds),
-                    type_default.as_ref(),
-                    ti.span,
-                );
-                self.push_rewrite(ti.span, rewrite);
+            (ast::AssocItemKind::TyAlias(ref ty_alias), _) => {
+                self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
             }
-            ast::AssocItemKind::MacCall(ref mac) => {
-                self.visit_mac(mac, Some(ti.ident), MacroPosition::Item);
+            (ast::AssocItemKind::MacCall(ref mac), _) => {
+                self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
             }
+            _ => unreachable!(),
         }
     }
 
-    pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
-        skip_out_of_file_lines_range_visitor!(self, ii.span);
-
-        if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ii.attrs.as_slice(), ii.span, ii.span);
-            return;
-        }
+    pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
+        self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
+    }
 
-        match ii.kind {
-            ast::AssocItemKind::Fn(ref fn_kind) => {
-                let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
-                if let Some(ref body) = block {
-                    let inner_attrs = inner_attributes(&ii.attrs);
-                    let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl);
-                    self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)),
-                        generics,
-                        &sig.decl,
-                        ii.span,
-                        defaultness,
-                        Some(&inner_attrs),
-                    );
-                } else {
-                    let indent = self.block_indent;
-                    let rewrite =
-                        self.rewrite_required_fn(indent, ii.ident, sig, &ii.vis, generics, ii.span);
-                    self.push_rewrite(ii.span, rewrite);
-                }
-            }
-            ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)),
-            ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
-                let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind;
-                self.push_rewrite(
-                    ii.span,
-                    rewrite_impl_type(
-                        ii.ident,
-                        &ii.vis,
-                        defaultness,
-                        ty.as_ref(),
-                        &generics,
-                        &self.get_context(),
-                        self.block_indent,
-                        ii.span,
-                    ),
-                );
-            }
-            ast::AssocItemKind::MacCall(ref mac) => {
-                self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
-            }
-        }
+    pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
+        self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
     }
 
     fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {
@@ -905,7 +848,7 @@ fn is_unknown_rustfmt_attr(&self, segments: &[ast::PathSegment]) -> bool {
     }
 
     fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) {
-        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items));
+        self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items));
     }
 
     fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) {
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs
new file mode 100644 (file)
index 0000000..d569747
--- /dev/null
@@ -0,0 +1,2 @@
+mod bar {
+        mod baz;}
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs
new file mode 100644 (file)
index 0000000..3519b0e
--- /dev/null
@@ -0,0 +1 @@
+fn    baz()    {       }
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs
new file mode 100644 (file)
index 0000000..41c81c7
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    println!("Hello, world!");
+}
+
+mod foo;
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs
new file mode 100644 (file)
index 0000000..157d385
--- /dev/null
@@ -0,0 +1,17 @@
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+use alloc::vec::Vec;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs
new file mode 100644 (file)
index 0000000..109bd07
--- /dev/null
@@ -0,0 +1,7 @@
+// rustfmt-group_imports: One
+mod test {
+    use crate::foo::bar;
+
+    use std::path;
+    use crate::foo::bar2;
+}
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs
new file mode 100644 (file)
index 0000000..f82f62c
--- /dev/null
@@ -0,0 +1,16 @@
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/source/configs/group_imports/One.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One.rs
new file mode 100644 (file)
index 0000000..5ab7a95
--- /dev/null
@@ -0,0 +1,15 @@
+// rustfmt-group_imports: One
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs
new file mode 100644 (file)
index 0000000..20c5bc8
--- /dev/null
@@ -0,0 +1,46 @@
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+
+}
+
+struct Struct
+{
+
+}
+
+enum Enum
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read, {}
index 38094d67a77374b289a06cae9e0fbdf5e49c29a8..0fb6405120aa7c5d7205c3bd6b126383ac36d1c2 100644 (file)
@@ -27,3 +27,38 @@ enum C<T> where T: Copy {}
 
     struct D<T> where T: Copy {}
 }
+
+
+fn function()
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read, {}
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs
new file mode 100644 (file)
index 0000000..52e0e1c
--- /dev/null
@@ -0,0 +1,14 @@
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use super::{
+    schema::{Context, Payload},
+    update::convert_publish_payload,
+};
+use crate::models::Event;
+use alloc::{alloc::Layout, vec::Vec};
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs
new file mode 100644 (file)
index 0000000..5b64854
--- /dev/null
@@ -0,0 +1,6 @@
+// rustfmt-group_imports: One
+mod test {
+    use crate::foo::bar;
+    use crate::foo::bar2;
+    use std::path;
+}
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs
new file mode 100644 (file)
index 0000000..015e841
--- /dev/null
@@ -0,0 +1,12 @@
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+use std::sync::Arc;
+use broker::database::PooledConnection;
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
diff --git a/src/tools/rustfmt/tests/target/configs/group_imports/One.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One.rs
new file mode 100644 (file)
index 0000000..3094c7a
--- /dev/null
@@ -0,0 +1,11 @@
+// rustfmt-group_imports: One
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
diff --git a/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs
new file mode 100644 (file)
index 0000000..bf7f70e
--- /dev/null
@@ -0,0 +1,41 @@
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+}
+
+struct Struct {}
+
+enum Enum {}
+
+trait Trait
+{
+}
+
+impl<T> Trait for T
+{
+}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read,
+{
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs
new file mode 100644 (file)
index 0000000..ff9c40f
--- /dev/null
@@ -0,0 +1,8 @@
+// rustfmt-trailing_comma: Always
+
+pub struct Matrix<T, const R: usize, const C: usize,>
+where
+    [T; R * C]:,
+{
+    contents: [T; R * C],
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs
new file mode 100644 (file)
index 0000000..2fac8ea
--- /dev/null
@@ -0,0 +1,8 @@
+// rustfmt-trailing_comma: Never
+
+pub struct Matrix<T, const R: usize, const C: usize>
+where
+    [T; R * C]:
+{
+    contents: [T; R * C]
+}
diff --git a/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs
new file mode 100644 (file)
index 0000000..0e7df41
--- /dev/null
@@ -0,0 +1,8 @@
+// leading comment
+
+#![rustfmt::skip]
+fn main() {
+    println!("main"); // commented
+}
+
+// post comment
diff --git a/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs b/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs
new file mode 100644 (file)
index 0000000..7a11133
--- /dev/null
@@ -0,0 +1,11 @@
+#![rustfmt::skip]
+
+mod a {
+    mod b {
+
+    }
+
+    // trailing comment b
+}
+
+// trailing comment a
diff --git a/src/tools/rustfmt/tests/target/issue_4850.rs b/src/tools/rustfmt/tests/target/issue_4850.rs
new file mode 100644 (file)
index 0000000..7d4da90
--- /dev/null
@@ -0,0 +1,4 @@
+impl ThisIsALongStructNameToPushTheWhereToWrapLolololol where
+    [(); this_is_a_long_const_function_name()]:
+{
+}
index 531ac59868314054c6ef5d36707f7f08f64613b7..4935fac04f1111cec322b7443c9f7b58c2677eef 100644 (file)
@@ -40,3 +40,32 @@ struct D<T>
     where
         T: Copy, {}
 }
+
+fn function() {}
+
+trait Trait {}
+
+impl<T> Trait for T {}
+
+trait Trait2<T>
+where
+    T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+    T: Something
+        + SomethingElse
+        + Sync
+        + Send
+        + Display
+        + Debug
+        + Copy
+        + Hash
+        + Debug
+        + Display
+        + Write
+        + Read,
+{
+}
index a20ea3235ed46348fc07ac468a1c94c9c84b689f..09848462ae207f9bbcfd2d2c6c529c1905c492f3 100644 (file)
@@ -60,6 +60,7 @@ fn filter_dirs(path: &Path) -> bool {
         "compiler/rustc_codegen_gcc",
         "src/llvm-project",
         "library/backtrace",
+        "library/portable-simd",
         "library/stdarch",
         "src/tools/cargo",
         "src/tools/clippy",
index 4afa36502aca1c063e2caec6a225df919a7e0c5d..88ede45655c94411b89b3bc110c3879279d00ede 100644 (file)
@@ -7,8 +7,8 @@
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1331;
-const ISSUES_ENTRY_LIMIT: usize = 2488;
+const ROOT_ENTRY_LIMIT: usize = 1275;
+const ISSUES_ENTRY_LIMIT: usize = 2310;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))