From 60c5eb7d04ee1e0108714fd93e704431aa9cf68e Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Sun, 8 Mar 2020 23:20:00 +0000 Subject: [PATCH] New upstream version 1.41.1+dfsg1 --- CONTRIBUTING.md | 8 +- Cargo.lock | 1024 +- README.md | 2 +- RELEASES.md | 264 +- config.toml.example | 3 - git-commit-hash | 2 +- src/bootstrap/bin/rustdoc.rs | 2 +- src/bootstrap/bootstrap.py | 55 +- src/bootstrap/builder.rs | 33 +- src/bootstrap/builder/tests.rs | 4 + src/bootstrap/channel.rs | 33 +- src/bootstrap/check.rs | 66 +- src/bootstrap/compile.rs | 336 +- src/bootstrap/config.rs | 19 +- src/bootstrap/dist.rs | 30 +- src/bootstrap/doc.rs | 4 +- src/bootstrap/flags.rs | 6 +- src/bootstrap/install.rs | 2 +- src/bootstrap/lib.rs | 37 +- src/bootstrap/native.rs | 4 +- src/bootstrap/test.rs | 7 +- src/bootstrap/toolstate.rs | 407 + src/bootstrap/util.rs | 17 + src/ci/azure-pipelines/auto.yml | 217 +- src/ci/azure-pipelines/master.yml | 5 +- src/ci/azure-pipelines/pr.yml | 7 +- src/ci/azure-pipelines/steps/run.yml | 92 +- src/ci/azure-pipelines/try.yml | 7 +- src/ci/docker/README.md | 7 + src/ci/docker/armhf-gnu/Dockerfile | 2 +- .../docker/dist-armv7-linux/crosstool-ng.sh | 2 +- src/ci/docker/dist-i686-linux/Dockerfile | 2 +- src/ci/docker/dist-various-1/Dockerfile | 10 +- .../dist-various-1/install-mips-musl.sh | 2 +- .../dist-various-1/install-mipsel-musl.sh | 2 +- .../dist-various-2/build-wasi-toolchain.sh | 14 +- src/ci/docker/dist-x86_64-linux/Dockerfile | 2 +- .../docker/dist-x86_64-linux/build-clang.sh | 5 +- src/ci/docker/dist-x86_64-linux/build-curl.sh | 3 + .../docker/dist-x86_64-linux/build-openssl.sh | 4 + .../build-netbsd-toolchain.sh | 2 +- src/ci/docker/mingw-check/Dockerfile | 5 +- .../docker/mingw-check/validate-toolstate.sh | 19 + src/ci/docker/run.sh | 2 + src/ci/docker/scripts/freebsd-toolchain.sh | 2 +- src/ci/docker/scripts/sccache.sh | 2 +- .../Dockerfile | 6 +- src/ci/docker/x86_64-gnu-tools/Dockerfile | 4 +- .../x86_64-gnu-tools/checkregression.py | 48 - src/ci/docker/x86_64-gnu-tools/checktools.sh | 116 +- src/ci/docker/x86_64-gnu-tools/repo.sh | 68 - src/ci/publish_toolstate.sh | 33 + src/ci/run.sh | 4 +- src/ci/scripts/clean-disk.sh | 16 + src/ci/scripts/collect-cpu-stats.sh | 9 + src/ci/scripts/install-clang.sh | 25 +- src/ci/scripts/install-mingw.sh | 37 +- src/ci/scripts/install-msys2.sh | 6 +- src/ci/scripts/run-build-from-ci.sh | 21 + src/ci/scripts/setup-environment.sh | 31 + src/ci/shared.sh | 73 +- src/doc/book/ci/dictionary.txt | 1 - src/doc/book/src/ch04-03-slices.md | 2 +- ...ng-modules-to-control-scope-and-privacy.md | 2 +- src/doc/book/src/ch10-00-generics.md | 2 +- src/doc/book/src/ch16-03-shared-state.md | 139 +- src/doc/book/src/ch20-02-multithreaded.md | 115 +- .../ch20-03-graceful-shutdown-and-cleanup.md | 14 +- .../edition-guide/.github/workflows/main.yml | 28 + src/doc/edition-guide/.travis.yml | 9 - src/doc/edition-guide/README.md | 2 - ...o-workspaces-for-multi-package-projects.md | 2 +- .../rustup-for-managing-rust-versions.md | 2 +- src/doc/nomicon/.github/workflows/main.yml | 28 + src/doc/nomicon/.travis.yml | 14 - src/doc/nomicon/README.md | 2 +- src/doc/nomicon/src/other-reprs.md | 4 +- src/doc/reference/.github/workflows/main.yml | 32 + src/doc/reference/.travis.yml | 13 - src/doc/reference/CONTRIBUTING.md | 2 +- src/doc/reference/book.toml | 2 +- src/doc/reference/src/abi.md | 5 +- src/doc/reference/src/attributes/codegen.md | 3 +- .../reference/src/attributes/type_system.md | 6 +- .../reference/src/conditional-compilation.md | 2 + .../reference/src/crates-and-source-files.md | 7 +- .../reference/src/expressions/array-expr.md | 2 +- .../reference/src/expressions/await-expr.md | 1 + .../reference/src/expressions/field-expr.md | 1 + src/doc/reference/src/expressions/if-expr.md | 3 + .../reference/src/expressions/loop-expr.md | 4 + .../reference/src/expressions/match-expr.md | 15 +- .../src/expressions/operator-expr.md | 4 +- src/doc/reference/src/glossary.md | 42 + src/doc/reference/src/introduction.md | 4 +- .../reference/src/items/associated-items.md | 4 +- src/doc/reference/src/items/enumerations.md | 48 +- src/doc/reference/src/items/extern-crates.md | 2 + .../reference/src/items/external-blocks.md | 9 +- src/doc/reference/src/items/functions.md | 6 +- src/doc/reference/src/items/generics.md | 3 +- .../reference/src/items/implementations.md | 32 +- src/doc/reference/src/items/modules.md | 5 +- src/doc/reference/src/items/traits.md | 39 +- src/doc/reference/src/items/unions.md | 16 +- .../reference/src/items/use-declarations.md | 9 +- src/doc/reference/src/lifetime-elision.md | 135 +- src/doc/reference/src/linkage.md | 8 +- src/doc/reference/src/macros-by-example.md | 4 + src/doc/reference/src/paths.md | 17 +- src/doc/reference/src/procedural-macros.md | 17 +- src/doc/reference/src/runtime.md | 7 +- .../reference/src/special-types-and-traits.md | 8 +- src/doc/reference/src/tokens.md | 2 +- src/doc/reference/src/trait-bounds.md | 4 +- src/doc/reference/src/type-layout.md | 1 + src/doc/reference/src/types/closure.md | 5 +- src/doc/reference/src/types/inferred.md | 2 +- src/doc/reference/src/types/never.md | 14 + src/doc/rust-by-example/src/crates.md | 2 +- .../multiple_error_types/option_result.md | 4 +- src/doc/rustc-guide/.travis.yml | 5 +- src/doc/rustc-guide/README.md | 42 + src/doc/rustc-guide/book.toml | 10 +- .../rustc-guide/ci/build-ignore-timeouts.sh | 29 - src/doc/rustc-guide/ci/install.sh | 4 +- src/doc/rustc-guide/src/SUMMARY.md | 25 +- .../rustc-guide/src/appendix/background.md | 35 + .../rustc-guide/src/appendix/bibliography.md | 4 +- .../rustc-guide/src/appendix/code-index.md | 6 +- .../src/appendix/compiler-lecture.md | 51 + src/doc/rustc-guide/src/appendix/glossary.md | 5 +- src/doc/rustc-guide/src/borrow_check.md | 2 +- .../moves_and_initialization/move_paths.md | 1 + .../src/borrow_check/region_inference.md | 4 +- .../region_inference/member_constraints.md | 2 +- .../rustc-guide/src/building/bootstrapping.md | 161 + .../build-install-distribution-artifacts.md | 0 .../src/building/compiler-documenting.md | 52 + src/doc/rustc-guide/src/building/ctags.md | 26 + .../src/building/how-to-build-and-run.md | 277 + src/doc/rustc-guide/src/building/suggested.md | 78 + src/doc/rustc-guide/src/closure.md | 10 +- .../src/codegen/backend-agnostic.md | 205 + src/doc/rustc-guide/src/codegen/debugging.md | 48 +- .../rustc-guide/src/codegen/updating-llvm.md | 90 +- src/doc/rustc-guide/src/compiler-debugging.md | 4 +- .../rustc-guide/src/compiler-documenting.md | 62 - src/doc/rustc-guide/src/conventions.md | 14 +- src/doc/rustc-guide/src/diagnostics.md | 242 +- .../src/diagnostics/json-format.md | 0 .../rustc-guide/src/diagnostics/lintstore.md | 105 + src/doc/rustc-guide/src/generic_arguments.md | 50 + .../rustc-guide/src/high-level-overview.md | 8 +- src/doc/rustc-guide/src/hir.md | 2 +- .../rustc-guide/src/how-to-build-and-run.md | 533 - src/doc/rustc-guide/src/ice-breaker/about.md | 68 + src/doc/rustc-guide/src/ice-breaker/llvm.md | 31 + .../src/implementing_new_features.md | 55 +- src/doc/rustc-guide/src/important-links.md | 16 - src/doc/rustc-guide/src/kinds.md | 49 - src/doc/rustc-guide/src/macro-expansion.md | 722 +- src/doc/rustc-guide/src/mir/construction.md | 2 +- src/doc/rustc-guide/src/mir/index.md | 4 +- src/doc/rustc-guide/src/mir/optimizations.md | 48 + src/doc/rustc-guide/src/mir/passes.md | 2 +- src/doc/rustc-guide/src/miri.md | 164 +- .../rustc-guide/src/profiling/with_perf.md | 50 +- src/doc/rustc-guide/src/rustc-driver.md | 18 +- src/doc/rustc-guide/src/salsa.md | 214 + src/doc/rustc-guide/src/sanitizers.md | 68 + src/doc/rustc-guide/src/stability.md | 87 +- .../rustc-guide/src/test-implementation.md | 2 +- src/doc/rustc-guide/src/tests/adding.md | 13 +- src/doc/rustc-guide/src/tests/intro.md | 26 +- src/doc/rustc-guide/src/tests/running.md | 26 +- src/doc/rustc-guide/src/the-parser.md | 48 +- .../rustc-guide/src/traits/chalk-overview.md | 36 +- src/doc/rustc-guide/src/traits/slg.md | 16 +- src/doc/rustc-guide/src/traits/wf.md | 4 +- src/doc/rustc-guide/src/ty.md | 6 +- src/doc/rustc-guide/src/variance.md | 2 +- src/doc/rustc-guide/src/walkthrough.md | 16 +- src/doc/rustc/src/codegen-options/index.md | 229 +- src/doc/rustc/src/command-line-arguments.md | 129 +- src/doc/rustc/src/lints/levels.md | 2 +- .../src/lints/listing/deny-by-default.md | 91 +- .../src/lints/listing/warn-by-default.md | 52 - src/doc/rustdoc/src/SUMMARY.md | 3 + src/doc/rustdoc/src/advanced-features.md | 34 + src/doc/rustdoc/src/command-line-arguments.md | 33 +- src/doc/rustdoc/src/documentation-tests.md | 2 +- .../rustdoc/src/how-to-write-documentation.md | 82 + src/doc/rustdoc/src/lints.md | 119 + src/doc/rustdoc/src/unstable-features.md | 32 +- .../src/language-features/cfg-sanitize.md | 36 + .../src/language-features/const-if-match.md | 14 + .../src/language-features/doc-cfg.md | 4 +- .../src/language-features/on-unimplemented.md | 154 - .../src/language-features/plugin.md | 137 +- .../re-rebalance-coherence.md | 23 - src/etc/dec2flt_table.py | 15 +- src/etc/gdb_rust_pretty_printing.py | 12 +- src/etc/generate-deriving-span-tests.py | 3 +- src/etc/natvis/libstd.natvis | 102 + src/liballoc/alloc/tests.rs | 8 +- src/liballoc/benches/btree/map.rs | 63 +- src/liballoc/benches/btree/set.rs | 8 +- src/liballoc/benches/lib.rs | 1 + src/liballoc/benches/slice.rs | 63 +- src/liballoc/benches/str.rs | 35 +- src/liballoc/benches/vec_deque.rs | 2 +- src/liballoc/benches/vec_deque_append.rs | 5 +- src/liballoc/borrow.rs | 18 +- src/liballoc/boxed.rs | 80 + src/liballoc/collections/btree/map.rs | 115 + src/liballoc/collections/btree/mod.rs | 2 +- src/liballoc/collections/btree/node.rs | 2 +- src/liballoc/collections/btree/search.rs | 42 +- src/liballoc/collections/btree/set.rs | 110 +- src/liballoc/collections/linked_list.rs | 36 +- src/liballoc/collections/linked_list/tests.rs | 19 +- src/liballoc/collections/vec_deque.rs | 63 +- src/liballoc/collections/vec_deque/tests.rs | 55 +- src/liballoc/fmt.rs | 22 +- src/liballoc/lib.rs | 4 +- src/liballoc/macros.rs | 5 +- src/liballoc/prelude/v1.rs | 12 +- src/liballoc/raw_vec/tests.rs | 9 +- src/liballoc/rc.rs | 73 +- src/liballoc/rc/tests.rs | 14 +- src/liballoc/slice.rs | 173 +- src/liballoc/string.rs | 15 +- src/liballoc/sync.rs | 97 +- src/liballoc/sync/tests.rs | 18 +- src/liballoc/tests.rs | 6 +- src/liballoc/tests/arc.rs | 39 +- src/liballoc/tests/binary_heap.rs | 5 +- src/liballoc/tests/boxed.rs | 2 +- src/liballoc/tests/btree/map.rs | 45 + src/liballoc/tests/btree/mod.rs | 7 +- src/liballoc/tests/btree/set.rs | 28 + src/liballoc/tests/cow_str.rs | 3 + src/liballoc/tests/lib.rs | 1 + src/liballoc/tests/linked_list.rs | 182 +- src/liballoc/tests/rc.rs | 41 +- src/liballoc/tests/slice.rs | 30 +- src/liballoc/tests/str.rs | 15 +- src/liballoc/tests/string.rs | 4 +- src/liballoc/tests/vec.rs | 11 +- src/liballoc/tests/vec_deque.rs | 204 +- src/liballoc/vec.rs | 73 +- src/libarena/Cargo.toml | 2 +- src/libarena/lib.rs | 59 +- src/libcore/alloc.rs | 59 +- src/libcore/any.rs | 56 +- src/libcore/array/iter.rs | 35 +- src/libcore/array/mod.rs | 6 +- src/libcore/ascii.rs | 19 +- src/libcore/benches/any.rs | 2 +- src/libcore/benches/ascii.rs | 24 +- src/libcore/benches/char/methods.rs | 13 +- src/libcore/benches/fmt.rs | 2 +- src/libcore/benches/hash/sip.rs | 48 +- src/libcore/benches/iter.rs | 65 +- src/libcore/benches/lib.rs | 3 +- src/libcore/benches/num/flt2dec/mod.rs | 6 +- .../benches/num/flt2dec/strategy/dragon.rs | 2 +- .../benches/num/flt2dec/strategy/grisu.rs | 4 +- src/libcore/benches/num/mod.rs | 16 +- src/libcore/benches/ops.rs | 7 +- src/libcore/benches/pattern.rs | 43 + src/libcore/benches/slice.rs | 7 +- src/libcore/bool.rs | 24 +- src/libcore/cell.rs | 61 +- src/libcore/char/convert.rs | 32 +- src/libcore/char/decode.rs | 13 +- src/libcore/char/methods.rs | 39 +- src/libcore/char/mod.rs | 81 +- src/libcore/clone.rs | 31 +- src/libcore/cmp.rs | 57 +- src/libcore/{convert.rs => convert/mod.rs} | 98 +- src/libcore/convert/num.rs | 449 + src/libcore/default.rs | 4 +- src/libcore/ffi.rs | 284 +- src/libcore/fmt/float.rs | 125 +- src/libcore/fmt/mod.rs | 237 +- src/libcore/fmt/num.rs | 2 + src/libcore/hash/mod.rs | 18 +- src/libcore/hash/sip.rs | 115 +- src/libcore/hint.rs | 32 +- src/libcore/intrinsics.rs | 21 +- src/libcore/iter/adapters/chain.rs | 2 +- src/libcore/iter/adapters/flatten.rs | 128 +- src/libcore/iter/adapters/mod.rs | 14 +- src/libcore/iter/adapters/zip.rs | 2 + src/libcore/iter/range.rs | 8 +- src/libcore/iter/sources.rs | 62 +- src/libcore/iter/traits/accum.rs | 24 +- src/libcore/iter/traits/collect.rs | 13 +- src/libcore/iter/traits/double_ended.rs | 10 +- src/libcore/iter/traits/iterator.rs | 11 +- src/libcore/lib.rs | 8 +- src/libcore/{macros.rs => macros/mod.rs} | 267 +- src/libcore/macros/panic.md | 47 + src/libcore/marker.rs | 8 +- src/libcore/mem/manually_drop.rs | 10 +- src/libcore/mem/maybe_uninit.rs | 252 +- src/libcore/mem/mod.rs | 76 +- src/libcore/num/bignum.rs | 56 +- src/libcore/num/dec2flt/algorithm.rs | 18 +- src/libcore/num/dec2flt/mod.rs | 36 +- src/libcore/num/dec2flt/num.rs | 14 +- src/libcore/num/dec2flt/parse.rs | 2 +- src/libcore/num/dec2flt/rawfp.rs | 70 +- src/libcore/num/dec2flt/table.rs | 2456 +-- src/libcore/num/diy_float.rs | 13 +- src/libcore/num/f32.rs | 42 +- src/libcore/num/f64.rs | 45 +- src/libcore/num/flt2dec/decoder.rs | 33 +- src/libcore/num/flt2dec/mod.rs | 196 +- src/libcore/num/flt2dec/strategy/dragon.rs | 143 +- src/libcore/num/flt2dec/strategy/grisu.rs | 292 +- src/libcore/num/mod.rs | 888 +- src/libcore/num/wrapping.rs | 20 +- src/libcore/ops/arith.rs | 91 +- src/libcore/ops/bit.rs | 96 +- src/libcore/ops/deref.rs | 12 +- src/libcore/ops/function.rs | 56 +- src/libcore/ops/index.rs | 20 +- src/libcore/ops/mod.rs | 8 +- src/libcore/ops/range.rs | 15 +- src/libcore/ops/try.rs | 48 +- src/libcore/ops/unsize.rs | 27 +- src/libcore/option.rs | 84 +- src/libcore/panic.rs | 86 +- src/libcore/panicking.rs | 97 +- src/libcore/pin.rs | 83 +- src/libcore/prelude/v1.rs | 43 +- src/libcore/ptr/mod.rs | 330 +- src/libcore/ptr/non_null.rs | 42 +- src/libcore/ptr/unique.rs | 31 +- src/libcore/result.rs | 31 +- src/libcore/slice/memchr.rs | 2 + src/libcore/slice/mod.rs | 70 +- src/libcore/slice/sort.rs | 126 +- src/libcore/str/lossy.rs | 2 + src/libcore/str/mod.rs | 89 +- src/libcore/str/pattern.rs | 28 +- src/libcore/sync/atomic.rs | 160 +- src/libcore/task/mod.rs | 2 +- src/libcore/task/poll.rs | 20 +- src/libcore/task/wake.rs | 27 +- src/libcore/tests/any.rs | 23 +- src/libcore/tests/array.rs | 8 +- src/libcore/tests/ascii.rs | 130 +- src/libcore/tests/atomic.rs | 6 +- src/libcore/tests/bool.rs | 8 +- src/libcore/tests/cell.rs | 10 +- src/libcore/tests/char.rs | 26 +- src/libcore/tests/cmp.rs | 8 + src/libcore/tests/hash/mod.rs | 43 +- src/libcore/tests/hash/sip.rs | 291 +- src/libcore/tests/intrinsics.rs | 6 +- src/libcore/tests/manually_drop.rs | 2 +- src/libcore/tests/mem.rs | 10 +- src/libcore/tests/nonzero.rs | 31 +- src/libcore/tests/num/bignum.rs | 17 +- src/libcore/tests/num/dec2flt/mod.rs | 23 +- src/libcore/tests/num/dec2flt/parse.rs | 4 +- src/libcore/tests/num/dec2flt/rawfp.rs | 23 +- src/libcore/tests/num/flt2dec/estimator.rs | 22 +- src/libcore/tests/num/flt2dec/mod.rs | 5 +- src/libcore/tests/num/flt2dec/random.rs | 121 +- .../tests/num/flt2dec/strategy/dragon.rs | 3 +- .../tests/num/flt2dec/strategy/grisu.rs | 15 +- src/libcore/tests/num/int_macros.rs | 477 +- src/libcore/tests/num/uint_macros.rs | 320 +- src/libcore/tests/ops.rs | 31 +- src/libcore/tests/option.rs | 27 +- src/libcore/tests/ptr.rs | 65 +- src/libcore/tests/slice.rs | 119 +- src/libcore/tests/str_lossy.rs | 78 +- src/libcore/tests/time.rs | 51 +- src/libcore/tests/tuple.rs | 2 +- src/libcore/time.rs | 86 +- src/libcore/tuple.rs | 2 +- src/libcore/unicode/bool_trie.rs | 12 +- src/libcore/unicode/printable.py | 6 +- src/libcore/unicode/printable.rs | 9 +- src/libcore/unicode/tables.rs | 29 +- src/libcore/unicode/unicode.py | 36 +- src/libcore/unit.rs | 2 +- src/libfmt_macros/lib.rs | 64 +- src/libfmt_macros/tests.rs | 43 +- src/libpanic_unwind/dwarf/eh.rs | 2 +- src/libpanic_unwind/lib.rs | 11 +- src/libpanic_unwind/seh.rs | 26 +- src/libproc_macro/lib.rs | 1 - src/librustc/Cargo.toml | 13 +- src/librustc/arena.rs | 13 +- src/librustc/benches/dispatch.rs | 34 - src/librustc/benches/lib.rs | 61 +- src/librustc/benches/pattern.rs | 25 - src/librustc/dep_graph/dep_node.rs | 8 +- src/librustc/dep_graph/graph.rs | 21 +- src/librustc/dep_graph/mod.rs | 1 - src/librustc/error_codes.rs | 2349 --- src/librustc/hir/check_attr.rs | 2 + src/librustc/hir/def.rs | 63 +- src/librustc/hir/intravisit.rs | 17 +- src/librustc/hir/lowering.rs | 223 +- src/librustc/hir/lowering/expr.rs | 61 +- src/librustc/hir/lowering/item.rs | 167 +- src/librustc/hir/map/blocks.rs | 142 +- src/librustc/hir/map/collector.rs | 180 +- src/librustc/hir/map/definitions.rs | 273 +- src/librustc/hir/map/hir_id_validator.rs | 110 +- src/librustc/hir/map/mod.rs | 860 +- src/librustc/hir/mod.rs | 207 +- src/librustc/hir/pat_util.rs | 5 +- src/librustc/hir/print.rs | 84 +- src/librustc/ich/hcx.rs | 106 +- src/librustc/ich/impls_hir.rs | 33 - src/librustc/ich/impls_misc.rs | 7 - src/librustc/ich/impls_syntax.rs | 381 +- src/librustc/ich/impls_ty.rs | 5 - src/librustc/ich/mod.rs | 4 +- src/librustc/infer/canonical/canonicalizer.rs | 19 +- src/librustc/infer/canonical/mod.rs | 71 +- .../infer/canonical/query_response.rs | 3 +- src/librustc/infer/combine.rs | 17 +- src/librustc/infer/error_reporting/mod.rs | 323 +- .../infer/error_reporting/need_type_info.rs | 179 +- .../nice_region_error/different_lifetimes.rs | 4 +- .../nice_region_error/find_anon_type.rs | 6 +- .../error_reporting/nice_region_error/mod.rs | 2 +- .../nice_region_error/named_anon_conflict.rs | 4 +- .../nice_region_error/placeholder_error.rs | 8 +- .../nice_region_error/static_impl_trait.rs | 29 +- src/librustc/infer/error_reporting/note.rs | 22 +- src/librustc/infer/freshen.rs | 17 +- src/librustc/infer/fudge.rs | 3 +- src/librustc/infer/higher_ranked/mod.rs | 3 +- src/librustc/infer/mod.rs | 51 +- src/librustc/infer/nll_relate/mod.rs | 7 +- src/librustc/infer/opaque_types/mod.rs | 10 +- .../infer/outlives/free_region_map.rs | 6 +- src/librustc/infer/outlives/obligations.rs | 2 +- src/librustc/infer/outlives/verify.rs | 6 +- .../infer/region_constraints/README.md | 2 +- src/librustc/infer/region_constraints/mod.rs | 24 +- src/librustc/infer/resolve.rs | 5 +- src/librustc/infer/unify_key.rs | 3 +- src/librustc/lib.rs | 16 +- src/librustc/lint/builtin.rs | 118 +- src/librustc/lint/context.rs | 44 +- src/librustc/lint/internal.rs | 3 +- src/librustc/lint/levels.rs | 28 +- src/librustc/lint/mod.rs | 247 +- src/librustc/macros.rs | 258 - src/librustc/middle/cstore.rs | 29 +- src/librustc/middle/exported_symbols.rs | 7 +- src/librustc/middle/lang_items.rs | 3 +- src/librustc/middle/lib_features.rs | 44 +- src/librustc/middle/mem_categorization.rs | 1508 -- src/librustc/middle/reachable.rs | 6 +- src/librustc/middle/region.rs | 4 +- src/librustc/middle/resolve_lifetime.rs | 22 +- src/librustc/middle/stability.rs | 82 +- src/librustc/middle/weak_lang_items.rs | 2 + src/librustc/mir/cache.rs | 262 +- src/librustc/mir/interpret/allocation.rs | 6 +- src/librustc/mir/interpret/error.rs | 73 +- src/librustc/mir/interpret/mod.rs | 15 +- src/librustc/mir/interpret/pointer.rs | 31 +- src/librustc/mir/interpret/value.rs | 62 +- src/librustc/mir/mod.rs | 589 +- src/librustc/mir/mono.rs | 26 +- src/librustc/mir/tcx.rs | 28 +- src/librustc/mir/visit.rs | 68 +- src/librustc/query/mod.rs | 60 +- src/librustc/traits/auto_trait.rs | 176 +- src/librustc/traits/coherence.rs | 198 +- src/librustc/traits/error_reporting.rs | 993 +- src/librustc/traits/fulfill.rs | 30 +- src/librustc/traits/mod.rs | 92 +- src/librustc/traits/on_unimplemented.rs | 50 +- src/librustc/traits/project.rs | 12 +- src/librustc/traits/query/dropck_outlives.rs | 44 +- src/librustc/traits/query/method_autoderef.rs | 18 +- src/librustc/traits/query/mod.rs | 4 +- src/librustc/traits/query/normalize.rs | 19 +- src/librustc/traits/query/outlives_bounds.rs | 21 +- .../traits/query/type_op/ascribe_user_type.rs | 21 +- src/librustc/traits/query/type_op/eq.rs | 21 +- .../query/type_op/implied_outlives_bounds.rs | 19 +- .../traits/query/type_op/normalize.rs | 21 +- src/librustc/traits/query/type_op/outlives.rs | 23 +- .../traits/query/type_op/prove_predicate.rs | 19 +- src/librustc/traits/query/type_op/subtype.rs | 21 +- src/librustc/traits/select.rs | 387 +- src/librustc/traits/specialize/mod.rs | 4 +- .../traits/specialize/specialization_graph.rs | 9 +- src/librustc/traits/structural_impls.rs | 191 +- src/librustc/traits/util.rs | 2 +- src/librustc/ty/_match.rs | 5 +- src/librustc/ty/adjustment.rs | 19 +- src/librustc/ty/binding.rs | 15 +- src/librustc/ty/codec.rs | 3 + src/librustc/ty/constness.rs | 165 +- src/librustc/ty/context.rs | 144 +- src/librustc/ty/diagnostics.rs | 56 + src/librustc/ty/error.rs | 150 +- src/librustc/ty/flags.rs | 15 +- src/librustc/ty/fold.rs | 14 +- .../ty/inhabitedness/def_id_forest.rs | 10 +- src/librustc/ty/instance.rs | 120 +- src/librustc/ty/layout.rs | 338 +- src/librustc/ty/mod.rs | 136 +- src/librustc/ty/print/obsolete.rs | 56 +- src/librustc/ty/print/pretty.rs | 260 +- src/librustc/ty/query/config.rs | 2 +- src/librustc/ty/query/job.rs | 19 +- src/librustc/ty/query/mod.rs | 4 +- src/librustc/ty/query/on_disk_cache.rs | 7 +- src/librustc/ty/query/plumbing.rs | 48 +- src/librustc/ty/relate.rs | 86 +- src/librustc/ty/structural_impls.rs | 258 +- src/librustc/ty/sty.rs | 250 +- src/librustc/ty/subst.rs | 41 +- src/librustc/ty/util.rs | 28 +- src/librustc/ty/walk.rs | 3 +- src/librustc/ty/wf.rs | 108 +- src/librustc/util/common.rs | 16 +- src/librustc_apfloat/Cargo.toml | 2 +- src/librustc_codegen_llvm/Cargo.toml | 22 +- src/librustc_codegen_llvm/abi.rs | 53 +- src/librustc_codegen_llvm/allocator.rs | 1 + src/librustc_codegen_llvm/asm.rs | 4 +- src/librustc_codegen_llvm/attributes.rs | 57 +- src/librustc_codegen_llvm/back/lto.rs | 8 +- src/librustc_codegen_llvm/back/write.rs | 89 +- src/librustc_codegen_llvm/builder.rs | 6 +- src/librustc_codegen_llvm/callee.rs | 22 +- src/librustc_codegen_llvm/common.rs | 8 +- src/librustc_codegen_llvm/consts.rs | 24 +- src/librustc_codegen_llvm/context.rs | 12 +- .../debuginfo/create_scope_map.rs | 6 +- src/librustc_codegen_llvm/debuginfo/doc.rs | 2 +- src/librustc_codegen_llvm/debuginfo/gdb.rs | 1 + .../debuginfo/metadata.rs | 368 +- src/librustc_codegen_llvm/debuginfo/mod.rs | 67 +- .../debuginfo/namespace.rs | 6 +- .../debuginfo/source_loc.rs | 1 + src/librustc_codegen_llvm/declare.rs | 48 +- src/librustc_codegen_llvm/intrinsic.rs | 127 +- src/librustc_codegen_llvm/lib.rs | 29 +- src/librustc_codegen_llvm/llvm/ffi.rs | 27 +- src/librustc_codegen_llvm/llvm/mod.rs | 39 +- src/librustc_codegen_llvm/llvm_util.rs | 8 +- src/librustc_codegen_llvm/metadata.rs | 2 + src/librustc_codegen_llvm/mono_item.rs | 23 +- src/librustc_codegen_llvm/type_.rs | 11 +- src/librustc_codegen_llvm/type_of.rs | 18 +- src/librustc_codegen_ssa/Cargo.toml | 4 +- src/librustc_codegen_ssa/back/command.rs | 2 +- src/librustc_codegen_ssa/back/linker.rs | 3 +- src/librustc_codegen_ssa/back/rpath.rs | 6 +- src/librustc_codegen_ssa/back/rpath/tests.rs | 4 +- .../back/symbol_export.rs | 14 +- src/librustc_codegen_ssa/back/write.rs | 43 +- src/librustc_codegen_ssa/base.rs | 91 +- src/librustc_codegen_ssa/common.rs | 2 + .../debuginfo/type_names.rs | 18 +- src/librustc_codegen_ssa/error_codes.rs | 71 - src/librustc_codegen_ssa/lib.rs | 30 +- src/librustc_codegen_ssa/meth.rs | 19 +- src/librustc_codegen_ssa/mir/analyze.rs | 118 +- src/librustc_codegen_ssa/mir/block.rs | 266 +- src/librustc_codegen_ssa/mir/constant.rs | 31 +- src/librustc_codegen_ssa/mir/debuginfo.rs | 139 +- src/librustc_codegen_ssa/mir/mod.rs | 90 +- src/librustc_codegen_ssa/mir/operand.rs | 38 +- src/librustc_codegen_ssa/mir/place.rs | 46 +- src/librustc_codegen_ssa/mir/rvalue.rs | 60 +- src/librustc_codegen_ssa/mir/statement.rs | 2 + src/librustc_codegen_ssa/traits/abi.rs | 4 +- src/librustc_codegen_ssa/traits/asm.rs | 4 +- src/librustc_codegen_ssa/traits/backend.rs | 11 +- src/librustc_codegen_ssa/traits/builder.rs | 9 +- src/librustc_codegen_ssa/traits/debuginfo.rs | 5 +- src/librustc_codegen_ssa/traits/declare.rs | 19 +- src/librustc_codegen_ssa/traits/intrinsic.rs | 4 +- src/librustc_codegen_ssa/traits/mod.rs | 6 +- src/librustc_codegen_ssa/traits/type_.rs | 14 +- src/librustc_codegen_utils/lib.rs | 38 +- .../symbol_names/legacy.rs | 7 +- src/librustc_codegen_utils/symbol_names/v0.rs | 11 +- src/librustc_data_structures/Cargo.toml | 4 +- src/librustc_data_structures/flock.rs | 12 - .../graph/dominators/mod.rs | 17 +- src/librustc_data_structures/jobserver.rs | 2 +- src/librustc_data_structures/lib.rs | 1 + .../obligation_forest/mod.rs | 363 +- .../obligation_forest/tests.rs | 30 +- .../profiling.rs | 49 +- src/librustc_data_structures/sharded.rs | 6 + src/librustc_data_structures/stable_hasher.rs | 12 +- src/librustc_data_structures/tiny_list.rs | 40 +- .../transitive_relation.rs | 8 + src/librustc_driver/Cargo.toml | 10 +- src/librustc_driver/args.rs | 12 +- src/librustc_driver/lib.rs | 325 +- src/librustc_driver/pretty.rs | 393 +- src/librustc_error_codes/Cargo.toml | 9 + src/librustc_error_codes/error_codes.rs | 612 + src/librustc_error_codes/error_codes/E0001.md | 24 + src/librustc_error_codes/error_codes/E0002.md | 29 + src/librustc_error_codes/error_codes/E0004.md | 46 + src/librustc_error_codes/error_codes/E0005.md | 30 + src/librustc_error_codes/error_codes/E0007.md | 18 + src/librustc_error_codes/error_codes/E0009.md | 48 + src/librustc_error_codes/error_codes/E0010.md | 11 + src/librustc_error_codes/error_codes/E0013.md | 18 + src/librustc_error_codes/error_codes/E0014.md | 20 + src/librustc_error_codes/error_codes/E0015.md | 33 + src/librustc_error_codes/error_codes/E0019.md | 36 + src/librustc_error_codes/error_codes/E0023.md | 57 + src/librustc_error_codes/error_codes/E0025.md | 34 + src/librustc_error_codes/error_codes/E0026.md | 34 + src/librustc_error_codes/error_codes/E0027.md | 39 + src/librustc_error_codes/error_codes/E0029.md | 26 + src/librustc_error_codes/error_codes/E0030.md | 15 + src/librustc_error_codes/error_codes/E0033.md | 27 + src/librustc_error_codes/error_codes/E0034.md | 86 + src/librustc_error_codes/error_codes/E0038.md | 291 + src/librustc_error_codes/error_codes/E0040.md | 39 + src/librustc_error_codes/error_codes/E0044.md | 15 + src/librustc_error_codes/error_codes/E0045.md | 21 + src/librustc_error_codes/error_codes/E0046.md | 31 + src/librustc_error_codes/error_codes/E0049.md | 36 + src/librustc_error_codes/error_codes/E0050.md | 36 + src/librustc_error_codes/error_codes/E0053.md | 21 + src/librustc_error_codes/error_codes/E0054.md | 20 + src/librustc_error_codes/error_codes/E0055.md | 28 + src/librustc_error_codes/error_codes/E0057.md | 22 + src/librustc_error_codes/error_codes/E0059.md | 25 + src/librustc_error_codes/error_codes/E0060.md | 36 + src/librustc_error_codes/error_codes/E0061.md | 23 + src/librustc_error_codes/error_codes/E0062.md | 30 + src/librustc_error_codes/error_codes/E0063.md | 27 + src/librustc_error_codes/error_codes/E0067.md | 15 + src/librustc_error_codes/error_codes/E0069.md | 14 + src/librustc_error_codes/error_codes/E0070.md | 49 + src/librustc_error_codes/error_codes/E0071.md | 27 + src/librustc_error_codes/error_codes/E0072.md | 37 + src/librustc_error_codes/error_codes/E0073.md | 19 + src/librustc_error_codes/error_codes/E0074.md | 24 + src/librustc_error_codes/error_codes/E0075.md | 23 + src/librustc_error_codes/error_codes/E0076.md | 24 + src/librustc_error_codes/error_codes/E0077.md | 23 + src/librustc_error_codes/error_codes/E0080.md | 20 + src/librustc_error_codes/error_codes/E0081.md | 37 + src/librustc_error_codes/error_codes/E0084.md | 27 + src/librustc_error_codes/error_codes/E0087.md | 15 + src/librustc_error_codes/error_codes/E0088.md | 45 + src/librustc_error_codes/error_codes/E0089.md | 25 + src/librustc_error_codes/error_codes/E0090.md | 22 + src/librustc_error_codes/error_codes/E0091.md | 16 + src/librustc_error_codes/error_codes/E0092.md | 24 + src/librustc_error_codes/error_codes/E0093.md | 35 + src/librustc_error_codes/error_codes/E0094.md | 24 + src/librustc_error_codes/error_codes/E0106.md | 53 + src/librustc_error_codes/error_codes/E0107.md | 44 + src/librustc_error_codes/error_codes/E0109.md | 22 + src/librustc_error_codes/error_codes/E0110.md | 4 + src/librustc_error_codes/error_codes/E0116.md | 27 + src/librustc_error_codes/error_codes/E0117.md | 50 + src/librustc_error_codes/error_codes/E0118.md | 43 + src/librustc_error_codes/error_codes/E0119.md | 59 + src/librustc_error_codes/error_codes/E0120.md | 36 + src/librustc_error_codes/error_codes/E0121.md | 10 + src/librustc_error_codes/error_codes/E0124.md | 18 + src/librustc_error_codes/error_codes/E0128.md | 24 + src/librustc_error_codes/error_codes/E0130.md | 31 + src/librustc_error_codes/error_codes/E0131.md | 8 + src/librustc_error_codes/error_codes/E0132.md | 32 + src/librustc_error_codes/error_codes/E0133.md | 31 + src/librustc_error_codes/error_codes/E0136.md | 16 + src/librustc_error_codes/error_codes/E0137.md | 24 + src/librustc_error_codes/error_codes/E0138.md | 25 + src/librustc_error_codes/error_codes/E0139.md | 84 + src/librustc_error_codes/error_codes/E0152.md | 25 + src/librustc_error_codes/error_codes/E0154.md | 33 + src/librustc_error_codes/error_codes/E0158.md | 38 + src/librustc_error_codes/error_codes/E0161.md | 30 + src/librustc_error_codes/error_codes/E0162.md | 26 + src/librustc_error_codes/error_codes/E0164.md | 24 + src/librustc_error_codes/error_codes/E0165.md | 27 + src/librustc_error_codes/error_codes/E0170.md | 46 + src/librustc_error_codes/error_codes/E0178.md | 19 + src/librustc_error_codes/error_codes/E0184.md | 6 + src/librustc_error_codes/error_codes/E0185.md | 19 + src/librustc_error_codes/error_codes/E0186.md | 19 + src/librustc_error_codes/error_codes/E0191.md | 22 + src/librustc_error_codes/error_codes/E0192.md | 4 + src/librustc_error_codes/error_codes/E0193.md | 44 + src/librustc_error_codes/error_codes/E0195.md | 34 + src/librustc_error_codes/error_codes/E0197.md | 13 + src/librustc_error_codes/error_codes/E0198.md | 27 + src/librustc_error_codes/error_codes/E0199.md | 14 + src/librustc_error_codes/error_codes/E0200.md | 14 + src/librustc_error_codes/error_codes/E0201.md | 45 + src/librustc_error_codes/error_codes/E0202.md | 5 + src/librustc_error_codes/error_codes/E0203.md | 18 + src/librustc_error_codes/error_codes/E0204.md | 25 + src/librustc_error_codes/error_codes/E0205.md | 29 + src/librustc_error_codes/error_codes/E0206.md | 12 + src/librustc_error_codes/error_codes/E0207.md | 131 + src/librustc_error_codes/error_codes/E0210.md | 82 + src/librustc_error_codes/error_codes/E0211.md | 79 + src/librustc_error_codes/error_codes/E0214.md | 12 + src/librustc_error_codes/error_codes/E0220.md | 41 + src/librustc_error_codes/error_codes/E0221.md | 43 + src/librustc_error_codes/error_codes/E0223.md | 32 + src/librustc_error_codes/error_codes/E0225.md | 18 + src/librustc_error_codes/error_codes/E0229.md | 36 + src/librustc_error_codes/error_codes/E0230.md | 29 + src/librustc_error_codes/error_codes/E0231.md | 27 + src/librustc_error_codes/error_codes/E0232.md | 22 + src/librustc_error_codes/error_codes/E0243.md | 13 + src/librustc_error_codes/error_codes/E0244.md | 13 + src/librustc_error_codes/error_codes/E0251.md | 21 + src/librustc_error_codes/error_codes/E0252.md | 54 + src/librustc_error_codes/error_codes/E0253.md | 19 + src/librustc_error_codes/error_codes/E0254.md | 36 + src/librustc_error_codes/error_codes/E0255.md | 44 + src/librustc_error_codes/error_codes/E0256.md | 18 + src/librustc_error_codes/error_codes/E0259.md | 23 + src/librustc_error_codes/error_codes/E0260.md | 34 + src/librustc_error_codes/error_codes/E0261.md | 53 + src/librustc_error_codes/error_codes/E0262.md | 8 + src/librustc_error_codes/error_codes/E0263.md | 7 + src/librustc_error_codes/error_codes/E0264.md | 22 + src/librustc_error_codes/error_codes/E0267.md | 20 + src/librustc_error_codes/error_codes/E0268.md | 19 + src/librustc_error_codes/error_codes/E0271.md | 80 + src/librustc_error_codes/error_codes/E0275.md | 20 + src/librustc_error_codes/error_codes/E0276.md | 19 + src/librustc_error_codes/error_codes/E0277.md | 85 + src/librustc_error_codes/error_codes/E0281.md | 20 + src/librustc_error_codes/error_codes/E0282.md | 65 + src/librustc_error_codes/error_codes/E0283.md | 49 + src/librustc_error_codes/error_codes/E0284.md | 42 + src/librustc_error_codes/error_codes/E0297.md | 40 + src/librustc_error_codes/error_codes/E0301.md | 17 + src/librustc_error_codes/error_codes/E0302.md | 15 + src/librustc_error_codes/error_codes/E0303.md | 28 + src/librustc_error_codes/error_codes/E0307.md | 78 + src/librustc_error_codes/error_codes/E0308.md | 17 + src/librustc_error_codes/error_codes/E0309.md | 50 + src/librustc_error_codes/error_codes/E0310.md | 20 + src/librustc_error_codes/error_codes/E0312.md | 30 + src/librustc_error_codes/error_codes/E0317.md | 14 + src/librustc_error_codes/error_codes/E0321.md | 19 + src/librustc_error_codes/error_codes/E0322.md | 4 + src/librustc_error_codes/error_codes/E0323.md | 45 + src/librustc_error_codes/error_codes/E0324.md | 37 + src/librustc_error_codes/error_codes/E0325.md | 45 + src/librustc_error_codes/error_codes/E0326.md | 16 + src/librustc_error_codes/error_codes/E0328.md | 34 + src/librustc_error_codes/error_codes/E0329.md | 40 + src/librustc_error_codes/error_codes/E0364.md | 32 + src/librustc_error_codes/error_codes/E0365.md | 32 + src/librustc_error_codes/error_codes/E0366.md | 30 + src/librustc_error_codes/error_codes/E0367.md | 35 + src/librustc_error_codes/error_codes/E0368.md | 47 + src/librustc_error_codes/error_codes/E0369.md | 28 + src/librustc_error_codes/error_codes/E0370.md | 33 + src/librustc_error_codes/error_codes/E0371.md | 17 + src/librustc_error_codes/error_codes/E0373.md | 48 + src/librustc_error_codes/error_codes/E0374.md | 55 + src/librustc_error_codes/error_codes/E0375.md | 52 + src/librustc_error_codes/error_codes/E0376.md | 45 + src/librustc_error_codes/error_codes/E0378.md | 57 + src/librustc_error_codes/error_codes/E0379.md | 4 + src/librustc_error_codes/error_codes/E0380.md | 4 + src/librustc_error_codes/error_codes/E0381.md | 20 + src/librustc_error_codes/error_codes/E0382.md | 110 + src/librustc_error_codes/error_codes/E0383.md | 34 + src/librustc_error_codes/error_codes/E0384.md | 20 + src/librustc_error_codes/error_codes/E0386.md | 31 + src/librustc_error_codes/error_codes/E0387.md | 57 + src/librustc_error_codes/error_codes/E0388.md | 1 + src/librustc_error_codes/error_codes/E0389.md | 63 + src/librustc_error_codes/error_codes/E0390.md | 28 + src/librustc_error_codes/error_codes/E0391.md | 14 + src/librustc_error_codes/error_codes/E0392.md | 57 + src/librustc_error_codes/error_codes/E0393.md | 28 + src/librustc_error_codes/error_codes/E0398.md | 35 + src/librustc_error_codes/error_codes/E0399.md | 35 + src/librustc_error_codes/error_codes/E0401.md | 106 + src/librustc_error_codes/error_codes/E0403.md | 25 + src/librustc_error_codes/error_codes/E0404.md | 43 + src/librustc_error_codes/error_codes/E0405.md | 29 + src/librustc_error_codes/error_codes/E0407.md | 52 + src/librustc_error_codes/error_codes/E0408.md | 41 + src/librustc_error_codes/error_codes/E0409.md | 38 + src/librustc_error_codes/error_codes/E0411.md | 56 + src/librustc_error_codes/error_codes/E0412.md | 64 + src/librustc_error_codes/error_codes/E0415.md | 14 + src/librustc_error_codes/error_codes/E0416.md | 28 + src/librustc_error_codes/error_codes/E0422.md | 21 + src/librustc_error_codes/error_codes/E0423.md | 47 + src/librustc_error_codes/error_codes/E0424.md | 40 + src/librustc_error_codes/error_codes/E0425.md | 60 + src/librustc_error_codes/error_codes/E0426.md | 17 + src/librustc_error_codes/error_codes/E0428.md | 16 + src/librustc_error_codes/error_codes/E0429.md | 21 + src/librustc_error_codes/error_codes/E0430.md | 18 + src/librustc_error_codes/error_codes/E0431.md | 11 + src/librustc_error_codes/error_codes/E0432.md | 32 + src/librustc_error_codes/error_codes/E0433.md | 17 + src/librustc_error_codes/error_codes/E0434.md | 42 + src/librustc_error_codes/error_codes/E0435.md | 21 + src/librustc_error_codes/error_codes/E0436.md | 47 + src/librustc_error_codes/error_codes/E0437.md | 22 + src/librustc_error_codes/error_codes/E0438.md | 22 + src/librustc_error_codes/error_codes/E0439.md | 22 + src/librustc_error_codes/error_codes/E0445.md | 29 + src/librustc_error_codes/error_codes/E0446.md | 30 + src/librustc_error_codes/error_codes/E0447.md | 15 + src/librustc_error_codes/error_codes/E0448.md | 28 + src/librustc_error_codes/error_codes/E0449.md | 37 + src/librustc_error_codes/error_codes/E0451.md | 48 + src/librustc_error_codes/error_codes/E0452.md | 14 + src/librustc_error_codes/error_codes/E0453.md | 42 + src/librustc_error_codes/error_codes/E0454.md | 13 + src/librustc_error_codes/error_codes/E0455.md | 19 + src/librustc_error_codes/error_codes/E0458.md | 12 + src/librustc_error_codes/error_codes/E0459.md | 13 + src/librustc_error_codes/error_codes/E0463.md | 11 + src/librustc_error_codes/error_codes/E0466.md | 34 + src/librustc_error_codes/error_codes/E0468.md | 27 + src/librustc_error_codes/error_codes/E0469.md | 39 + src/librustc_error_codes/error_codes/E0478.md | 28 + src/librustc_error_codes/error_codes/E0491.md | 32 + src/librustc_error_codes/error_codes/E0492.md | 71 + src/librustc_error_codes/error_codes/E0493.md | 42 + src/librustc_error_codes/error_codes/E0495.md | 38 + src/librustc_error_codes/error_codes/E0496.md | 31 + src/librustc_error_codes/error_codes/E0497.md | 14 + src/librustc_error_codes/error_codes/E0499.md | 30 + src/librustc_error_codes/error_codes/E0500.md | 41 + src/librustc_error_codes/error_codes/E0501.md | 76 + src/librustc_error_codes/error_codes/E0502.md | 29 + src/librustc_error_codes/error_codes/E0503.md | 52 + src/librustc_error_codes/error_codes/E0504.md | 103 + src/librustc_error_codes/error_codes/E0505.md | 85 + src/librustc_error_codes/error_codes/E0506.md | 81 + src/librustc_error_codes/error_codes/E0507.md | 131 + src/librustc_error_codes/error_codes/E0508.md | 41 + src/librustc_error_codes/error_codes/E0509.md | 92 + src/librustc_error_codes/error_codes/E0510.md | 16 + src/librustc_error_codes/error_codes/E0511.md | 32 + src/librustc_error_codes/error_codes/E0512.md | 24 + src/librustc_error_codes/error_codes/E0515.md | 37 + src/librustc_error_codes/error_codes/E0516.md | 16 + src/librustc_error_codes/error_codes/E0517.md | 45 + src/librustc_error_codes/error_codes/E0518.md | 23 + src/librustc_error_codes/error_codes/E0520.md | 59 + src/librustc_error_codes/error_codes/E0522.md | 14 + src/librustc_error_codes/error_codes/E0524.md | 60 + src/librustc_error_codes/error_codes/E0525.md | 40 + src/librustc_error_codes/error_codes/E0527.md | 28 + src/librustc_error_codes/error_codes/E0528.md | 31 + src/librustc_error_codes/error_codes/E0529.md | 24 + src/librustc_error_codes/error_codes/E0530.md | 32 + src/librustc_error_codes/error_codes/E0531.md | 42 + src/librustc_error_codes/error_codes/E0532.md | 38 + src/librustc_error_codes/error_codes/E0533.md | 34 + src/librustc_error_codes/error_codes/E0534.md | 35 + src/librustc_error_codes/error_codes/E0535.md | 28 + src/librustc_error_codes/error_codes/E0536.md | 22 + src/librustc_error_codes/error_codes/E0537.md | 28 + src/librustc_error_codes/error_codes/E0538.md | 27 + src/librustc_error_codes/error_codes/E0541.md | 29 + src/librustc_error_codes/error_codes/E0550.md | 16 + src/librustc_error_codes/error_codes/E0551.md | 16 + src/librustc_error_codes/error_codes/E0552.md | 27 + src/librustc_error_codes/error_codes/E0554.md | 12 + src/librustc_error_codes/error_codes/E0556.md | 16 + src/librustc_error_codes/error_codes/E0557.md | 9 + src/librustc_error_codes/error_codes/E0559.md | 22 + src/librustc_error_codes/error_codes/E0560.md | 23 + src/librustc_error_codes/error_codes/E0561.md | 25 + src/librustc_error_codes/error_codes/E0562.md | 33 + src/librustc_error_codes/error_codes/E0565.md | 17 + src/librustc_error_codes/error_codes/E0566.md | 18 + src/librustc_error_codes/error_codes/E0567.md | 25 + src/librustc_error_codes/error_codes/E0568.md | 26 + src/librustc_error_codes/error_codes/E0569.md | 18 + src/librustc_error_codes/error_codes/E0570.md | 7 + src/librustc_error_codes/error_codes/E0571.md | 31 + src/librustc_error_codes/error_codes/E0572.md | 24 + src/librustc_error_codes/error_codes/E0573.md | 71 + src/librustc_error_codes/error_codes/E0574.md | 47 + src/librustc_error_codes/error_codes/E0575.md | 50 + src/librustc_error_codes/error_codes/E0576.md | 22 + src/librustc_error_codes/error_codes/E0577.md | 24 + src/librustc_error_codes/error_codes/E0578.md | 25 + src/librustc_error_codes/error_codes/E0579.md | 19 + src/librustc_error_codes/error_codes/E0580.md | 21 + src/librustc_error_codes/error_codes/E0581.md | 28 + src/librustc_error_codes/error_codes/E0582.md | 34 + src/librustc_error_codes/error_codes/E0583.md | 14 + src/librustc_error_codes/error_codes/E0584.md | 24 + src/librustc_error_codes/error_codes/E0585.md | 21 + src/librustc_error_codes/error_codes/E0586.md | 29 + src/librustc_error_codes/error_codes/E0587.md | 16 + src/librustc_error_codes/error_codes/E0588.md | 24 + src/librustc_error_codes/error_codes/E0589.md | 9 + src/librustc_error_codes/error_codes/E0590.md | 13 + src/librustc_error_codes/error_codes/E0591.md | 75 + src/librustc_error_codes/error_codes/E0592.md | 31 + src/librustc_error_codes/error_codes/E0593.md | 13 + src/librustc_error_codes/error_codes/E0594.md | 23 + src/librustc_error_codes/error_codes/E0595.md | 17 + src/librustc_error_codes/error_codes/E0596.md | 16 + src/librustc_error_codes/error_codes/E0597.md | 33 + src/librustc_error_codes/error_codes/E0599.md | 11 + src/librustc_error_codes/error_codes/E0600.md | 40 + src/librustc_error_codes/error_codes/E0601.md | 12 + src/librustc_error_codes/error_codes/E0602.md | 10 + src/librustc_error_codes/error_codes/E0603.md | 26 + src/librustc_error_codes/error_codes/E0604.md | 19 + src/librustc_error_codes/error_codes/E0605.md | 28 + src/librustc_error_codes/error_codes/E0606.md | 21 + src/librustc_error_codes/error_codes/E0607.md | 26 + src/librustc_error_codes/error_codes/E0608.md | 18 + src/librustc_error_codes/error_codes/E0609.md | 24 + src/librustc_error_codes/error_codes/E0610.md | 29 + src/librustc_error_codes/error_codes/E0614.md | 18 + src/librustc_error_codes/error_codes/E0615.md | 35 + src/librustc_error_codes/error_codes/E0616.md | 57 + src/librustc_error_codes/error_codes/E0617.md | 19 + src/librustc_error_codes/error_codes/E0618.md | 26 + src/librustc_error_codes/error_codes/E0619.md | 38 + src/librustc_error_codes/error_codes/E0620.md | 18 + src/librustc_error_codes/error_codes/E0621.md | 34 + src/librustc_error_codes/error_codes/E0622.md | 17 + src/librustc_error_codes/error_codes/E0623.md | 41 + src/librustc_error_codes/error_codes/E0624.md | 53 + src/librustc_error_codes/error_codes/E0626.md | 90 + src/librustc_error_codes/error_codes/E0631.md | 27 + src/librustc_error_codes/error_codes/E0633.md | 23 + src/librustc_error_codes/error_codes/E0635.md | 7 + src/librustc_error_codes/error_codes/E0636.md | 9 + src/librustc_error_codes/error_codes/E0638.md | 47 + src/librustc_error_codes/error_codes/E0639.md | 7 + src/librustc_error_codes/error_codes/E0641.md | 19 + src/librustc_error_codes/error_codes/E0642.md | 18 + src/librustc_error_codes/error_codes/E0643.md | 12 + src/librustc_error_codes/error_codes/E0644.md | 29 + src/librustc_error_codes/error_codes/E0646.md | 8 + src/librustc_error_codes/error_codes/E0647.md | 12 + src/librustc_error_codes/error_codes/E0648.md | 6 + src/librustc_error_codes/error_codes/E0658.md | 26 + src/librustc_error_codes/error_codes/E0659.md | 50 + src/librustc_error_codes/error_codes/E0660.md | 11 + src/librustc_error_codes/error_codes/E0661.md | 12 + src/librustc_error_codes/error_codes/E0662.md | 14 + src/librustc_error_codes/error_codes/E0663.md | 14 + src/librustc_error_codes/error_codes/E0664.md | 15 + src/librustc_error_codes/error_codes/E0665.md | 31 + src/librustc_error_codes/error_codes/E0666.md | 21 + src/librustc_error_codes/error_codes/E0668.md | 19 + src/librustc_error_codes/error_codes/E0669.md | 8 + src/librustc_error_codes/error_codes/E0670.md | 9 + src/librustc_error_codes/error_codes/E0671.md | 12 + src/librustc_error_codes/error_codes/E0689.md | 26 + src/librustc_error_codes/error_codes/E0690.md | 33 + src/librustc_error_codes/error_codes/E0691.md | 48 + src/librustc_error_codes/error_codes/E0692.md | 49 + src/librustc_error_codes/error_codes/E0695.md | 35 + src/librustc_error_codes/error_codes/E0697.md | 15 + src/librustc_error_codes/error_codes/E0698.md | 25 + src/librustc_error_codes/error_codes/E0699.md | 44 + src/librustc_error_codes/error_codes/E0700.md | 44 + src/librustc_error_codes/error_codes/E0701.md | 9 + src/librustc_error_codes/error_codes/E0704.md | 26 + src/librustc_error_codes/error_codes/E0705.md | 11 + src/librustc_error_codes/error_codes/E0706.md | 59 + src/librustc_error_codes/error_codes/E0712.md | 19 + src/librustc_error_codes/error_codes/E0713.md | 51 + src/librustc_error_codes/error_codes/E0714.md | 5 + src/librustc_error_codes/error_codes/E0715.md | 5 + src/librustc_error_codes/error_codes/E0716.md | 82 + src/librustc_error_codes/error_codes/E0718.md | 11 + src/librustc_error_codes/error_codes/E0720.md | 11 + src/librustc_error_codes/error_codes/E0723.md | 28 + src/librustc_error_codes/error_codes/E0725.md | 12 + src/librustc_error_codes/error_codes/E0728.md | 75 + src/librustc_error_codes/error_codes/E0729.md | 30 + src/librustc_error_codes/error_codes/E0730.md | 29 + src/librustc_error_codes/error_codes/E0731.md | 17 + src/librustc_error_codes/error_codes/E0732.md | 29 + src/librustc_error_codes/error_codes/E0733.md | 40 + src/librustc_error_codes/error_codes/E0734.md | 13 + src/librustc_error_codes/error_codes/E0735.md | 11 + src/librustc_error_codes/error_codes/E0736.md | 16 + src/librustc_error_codes/error_codes/E0737.md | 14 + src/librustc_error_codes/error_codes/E0738.md | 48 + src/librustc_error_codes/error_codes/E0740.md | 1 + src/librustc_error_codes/error_codes/E0741.md | 21 + src/librustc_error_codes/error_codes/E0742.md | 35 + src/librustc_error_codes/error_codes/E0743.md | 11 + src/librustc_error_codes/error_codes/E0744.md | 24 + src/librustc_error_codes/error_codes/E0745.md | 20 + src/librustc_error_codes/lib.rs | 21 + .../annotate_snippet_emitter_writer.rs | 11 +- src/librustc_errors/diagnostic.rs | 107 +- src/librustc_errors/diagnostic_builder.rs | 59 +- src/librustc_errors/emitter.rs | 655 +- src/{libsyntax => librustc_errors}/json.rs | 20 +- .../json/tests.rs | 29 +- src/librustc_errors/lib.rs | 312 +- src/librustc_feature/Cargo.toml | 15 + .../accepted.rs | 5 +- .../active.rs | 77 +- .../builtin_attrs.rs | 111 +- src/librustc_feature/lib.rs | 137 + .../removed.rs | 8 +- src/librustc_incremental/Cargo.toml | 1 + .../assert_module_sources.rs | 18 +- .../persist/dirty_clean.rs | 4 +- src/librustc_index/Cargo.toml | 2 +- src/librustc_interface/Cargo.toml | 13 +- src/librustc_interface/interface.rs | 62 +- src/librustc_interface/lib.rs | 2 + src/librustc_interface/passes.rs | 212 +- src/librustc_interface/queries.rs | 230 +- src/librustc_interface/tests.rs | 85 +- src/librustc_interface/util.rs | 174 +- src/librustc_lexer/src/cursor.rs | 12 +- src/librustc_lexer/src/lib.rs | 271 +- src/librustc_lint/Cargo.toml | 3 + src/librustc_lint/array_into_iter.rs | 91 + src/librustc_lint/builtin.rs | 120 +- src/librustc_lint/error_codes.rs | 4 - src/librustc_lint/lib.rs | 24 +- src/librustc_lint/types.rs | 83 +- src/librustc_lint/unused.rs | 29 +- src/librustc_llvm/Cargo.toml | 3 + src/librustc_llvm/lib.rs | 20 + src/librustc_macros/src/hash_stable.rs | 39 + src/librustc_macros/src/lib.rs | 9 + src/librustc_macros/src/lift.rs | 50 + src/librustc_macros/src/type_foldable.rs | 39 + src/librustc_metadata/Cargo.toml | 6 +- src/librustc_metadata/creader.rs | 454 +- src/librustc_metadata/cstore.rs | 180 - src/librustc_metadata/dependency_format.rs | 7 +- src/librustc_metadata/error_codes.rs | 97 - src/librustc_metadata/lib.rs | 10 +- src/librustc_metadata/link_args.rs | 2 +- src/librustc_metadata/locator.rs | 216 +- src/librustc_metadata/native_libs.rs | 40 +- src/librustc_metadata/{ => rmeta}/decoder.rs | 446 +- .../{ => rmeta/decoder}/cstore_impl.rs | 64 +- src/librustc_metadata/{ => rmeta}/encoder.rs | 191 +- .../{schema.rs => rmeta/mod.rs} | 289 +- src/librustc_metadata/{ => rmeta}/table.rs | 101 +- src/librustc_mir/Cargo.toml | 7 +- src/librustc_mir/borrow_check/borrow_set.rs | 17 +- .../{nll => }/constraint_generation.rs | 19 +- .../{nll => }/constraints/graph.rs | 9 +- .../borrow_check/{nll => }/constraints/mod.rs | 3 +- .../{ => diagnostics}/conflict_errors.rs | 412 +- .../mod.rs => diagnostics/explain_borrow.rs} | 34 +- .../find_use.rs | 3 +- .../mod.rs} | 125 +- .../{ => diagnostics}/move_errors.rs | 66 +- .../{ => diagnostics}/mutability_errors.rs | 161 +- .../diagnostics/outlives_suggestion.rs | 319 + .../mod.rs => diagnostics/region_errors.rs} | 96 +- .../region_name.rs | 155 +- .../var_name.rs | 14 +- .../borrow_check/{nll => }/facts.rs | 17 +- src/librustc_mir/borrow_check/flows.rs | 9 +- .../borrow_check/{nll => }/invalidation.rs | 29 +- .../{nll => }/member_constraints.rs | 0 src/librustc_mir/borrow_check/mod.rs | 348 +- .../borrow_check/{nll/mod.rs => nll.rs} | 127 +- src/librustc_mir/borrow_check/place_ext.rs | 63 +- .../borrow_check/places_conflict.rs | 48 +- src/librustc_mir/borrow_check/prefixes.rs | 10 +- .../{nll => }/region_infer/dump_mir.rs | 0 .../{nll => }/region_infer/graphviz.rs | 5 +- .../{nll => }/region_infer/mod.rs | 323 +- .../{nll => }/region_infer/values.rs | 4 +- .../borrow_check/{nll => }/renumber.rs | 6 +- .../type_check/constraint_conversion.rs | 13 +- .../type_check/free_region_relations.rs | 16 +- .../{nll => }/type_check/input_output.rs | 23 +- .../type_check/liveness/local_use_map.rs | 10 +- .../{nll => }/type_check/liveness/mod.rs | 29 +- .../{nll => }/type_check/liveness/polonius.rs | 68 +- .../{nll => }/type_check/liveness/trace.rs | 31 +- .../borrow_check/{nll => }/type_check/mod.rs | 488 +- .../{nll => }/type_check/relate_tys.rs | 5 +- .../{nll => }/universal_regions.rs | 26 +- src/librustc_mir/build/cfg.rs | 12 + src/librustc_mir/build/expr/as_constant.rs | 7 + src/librustc_mir/build/expr/as_place.rs | 302 +- src/librustc_mir/build/expr/as_rvalue.rs | 97 +- src/librustc_mir/build/expr/as_temp.rs | 6 + src/librustc_mir/build/expr/category.rs | 8 +- src/librustc_mir/build/expr/into.rs | 122 +- src/librustc_mir/build/matches/mod.rs | 102 +- src/librustc_mir/build/matches/test.rs | 14 +- src/librustc_mir/build/matches/util.rs | 34 +- src/librustc_mir/build/mod.rs | 245 +- src/librustc_mir/build/scope.rs | 63 +- src/librustc_mir/const_eval.rs | 120 +- src/librustc_mir/dataflow/impls/borrows.rs | 24 +- src/librustc_mir/dataflow/impls/mod.rs | 8 +- .../dataflow/impls/storage_liveness.rs | 10 +- .../dataflow/move_paths/abs_domain.rs | 4 +- .../dataflow/move_paths/builder.rs | 148 +- src/librustc_mir/dataflow/move_paths/mod.rs | 5 +- src/librustc_mir/error_codes.rs | 2552 --- src/librustc_mir/hair/constant.rs | 7 +- src/librustc_mir/hair/cx/block.rs | 1 + src/librustc_mir/hair/cx/expr.rs | 192 +- src/librustc_mir/hair/mod.rs | 19 +- src/librustc_mir/hair/pattern/_match.rs | 1600 +- src/librustc_mir/hair/pattern/check_match.rs | 353 +- src/librustc_mir/hair/pattern/mod.rs | 37 +- src/librustc_mir/interpret/cast.rs | 13 +- src/librustc_mir/interpret/eval_context.rs | 276 +- src/librustc_mir/interpret/intern.rs | 89 +- src/librustc_mir/interpret/intrinsics.rs | 250 +- .../interpret/intrinsics/caller_location.rs | 78 +- src/librustc_mir/interpret/machine.rs | 73 +- src/librustc_mir/interpret/memory.rs | 110 +- src/librustc_mir/interpret/mod.rs | 2 +- src/librustc_mir/interpret/operand.rs | 122 +- src/librustc_mir/interpret/operator.rs | 8 +- src/librustc_mir/interpret/place.rs | 131 +- src/librustc_mir/interpret/snapshot.rs | 60 +- src/librustc_mir/interpret/step.rs | 22 +- src/librustc_mir/interpret/terminator.rs | 213 +- src/librustc_mir/interpret/traits.rs | 85 +- src/librustc_mir/interpret/validity.rs | 344 +- src/librustc_mir/lib.rs | 7 +- src/librustc_mir/monomorphize/collector.rs | 85 +- src/librustc_mir/monomorphize/mod.rs | 2 +- src/librustc_mir/monomorphize/partitioning.rs | 6 +- src/librustc_mir/shim.rs | 152 +- src/librustc_mir/transform/add_call_guards.rs | 9 +- .../transform/add_moves_for_packed_drops.rs | 6 +- src/librustc_mir/transform/add_retag.rs | 2 +- .../transform/check_consts/mod.rs | 25 +- .../transform/check_consts/ops.rs | 154 +- .../transform/check_consts/qualifs.rs | 92 +- .../transform/check_consts/resolver.rs | 2 +- .../transform/check_consts/validation.rs | 476 +- src/librustc_mir/transform/check_unsafety.rs | 124 +- .../transform/cleanup_post_borrowck.rs | 6 +- src/librustc_mir/transform/const_prop.rs | 269 +- src/librustc_mir/transform/copy_prop.rs | 27 +- src/librustc_mir/transform/deaggregator.rs | 4 +- src/librustc_mir/transform/dump_mir.rs | 7 +- src/librustc_mir/transform/elaborate_drops.rs | 11 +- src/librustc_mir/transform/erase_regions.rs | 2 +- src/librustc_mir/transform/generator.rs | 125 +- src/librustc_mir/transform/inline.rs | 57 +- src/librustc_mir/transform/instcombine.rs | 8 +- src/librustc_mir/transform/mod.rs | 87 +- src/librustc_mir/transform/no_landing_pads.rs | 4 +- src/librustc_mir/transform/promote_consts.rs | 165 +- src/librustc_mir/transform/qualify_consts.rs | 1991 -- .../transform/qualify_min_const_fn.rs | 117 +- .../transform/remove_noop_landing_pads.rs | 6 +- src/librustc_mir/transform/rustc_peek.rs | 20 +- src/librustc_mir/transform/simplify.rs | 69 +- .../transform/simplify_branches.rs | 2 +- src/librustc_mir/transform/simplify_try.rs | 207 + .../transform/uniform_array_move_out.rs | 373 - .../transform/uninhabited_enum_branching.rs | 127 + src/librustc_mir/util/borrowck_errors.rs | 16 +- src/librustc_mir/util/collect_writes.rs | 6 +- src/librustc_mir/util/def_use.rs | 50 +- src/librustc_mir/util/elaborate_drops.rs | 4 +- src/librustc_mir/util/graphviz.rs | 14 +- src/librustc_mir/util/liveness.rs | 10 +- src/librustc_mir/util/patch.rs | 2 +- src/librustc_mir/util/pretty.rs | 26 +- src/librustc_parse/Cargo.toml | 22 + src/{libsyntax => librustc_parse}/config.rs | 170 +- .../parse => librustc_parse}/lexer/mod.rs | 45 +- .../lexer/tokentrees.rs | 13 +- .../lexer}/unescape_error_reporting.rs | 2 +- .../lexer/unicode_chars.rs | 4 +- .../parse/mod.rs => librustc_parse/lib.rs} | 77 +- .../parse => librustc_parse}/parser/attr.rs | 88 +- .../parser/diagnostics.rs | 133 +- .../parse => librustc_parse}/parser/expr.rs | 141 +- .../parser/generics.rs | 14 +- .../parse => librustc_parse}/parser/item.rs | 408 +- .../parser/mod.rs} | 235 +- .../parse => librustc_parse}/parser/module.rs | 70 +- .../parse => librustc_parse}/parser/pat.rs | 69 +- .../parse => librustc_parse}/parser/path.rs | 60 +- .../parse => librustc_parse}/parser/stmt.rs | 39 +- .../parse => librustc_parse}/parser/ty.rs | 32 +- src/librustc_parse/validate_attr.rs | 149 + src/librustc_passes/Cargo.toml | 7 +- src/librustc_passes/ast_validation.rs | 192 +- src/librustc_passes/check_const.rs | 253 + src/librustc_passes/dead.rs | 19 +- src/librustc_passes/entry.rs | 2 + src/librustc_passes/error_codes.rs | 635 - src/librustc_passes/intrinsicck.rs | 2 + src/librustc_passes/lib.rs | 5 +- src/librustc_passes/liveness.rs | 45 +- src/librustc_passes/loops.rs | 10 +- src/librustc_plugin/deprecated/Cargo.toml | 14 - src/librustc_plugin/deprecated/lib.rs | 8 - src/librustc_plugin/error_codes.rs | 4 - src/librustc_plugin/lib.rs | 65 - src/librustc_plugin/load.rs | 135 - src/librustc_plugin/registry.rs | 110 - .../Cargo.toml | 2 +- .../build.rs | 0 src/librustc_plugin_impl/lib.rs | 25 + src/librustc_plugin_impl/load.rs | 103 + src/librustc_privacy/Cargo.toml | 1 + src/librustc_privacy/error_codes.rs | 169 - src/librustc_privacy/lib.rs | 4 +- src/librustc_resolve/Cargo.toml | 4 +- src/librustc_resolve/build_reduced_graph.rs | 37 +- src/librustc_resolve/check_unused.rs | 4 +- .../map => librustc_resolve}/def_collector.rs | 45 +- src/librustc_resolve/diagnostics.rs | 66 +- src/librustc_resolve/error_codes.rs | 2048 -- src/librustc_resolve/late.rs | 117 +- src/librustc_resolve/late/diagnostics.rs | 2 + src/librustc_resolve/lib.rs | 138 +- src/librustc_resolve/macros.rs | 223 +- src/librustc_resolve/resolve_imports.rs | 30 +- src/librustc_save_analysis/Cargo.toml | 2 +- src/librustc_save_analysis/dump_visitor.rs | 54 +- src/librustc_save_analysis/lib.rs | 10 +- src/librustc_save_analysis/sig.rs | 45 +- src/librustc_save_analysis/span_utils.rs | 8 +- src/librustc_session/Cargo.toml | 21 + .../cgu_reuse_tracker.rs | 8 +- .../code_stats.rs | 21 +- .../session => librustc_session}/config.rs | 477 +- .../filesearch.rs | 7 +- src/librustc_session/lib.rs | 21 + src/librustc_session/lint.rs | 254 + src/librustc_session/node_id.rs | 39 + .../sess.rs => librustc_session/parse.rs} | 113 +- .../search_paths.rs | 8 +- .../mod.rs => librustc_session/session.rs} | 162 +- src/librustc_session/utils.rs | 25 + src/librustc_target/Cargo.toml | 1 + src/librustc_target/abi/call/aarch64.rs | 27 +- src/librustc_target/abi/call/amdgpu.rs | 16 +- src/librustc_target/abi/call/arm.rs | 31 +- src/librustc_target/abi/call/hexagon.rs | 16 +- src/librustc_target/abi/call/mips.rs | 16 +- src/librustc_target/abi/call/mips64.rs | 26 +- src/librustc_target/abi/call/mod.rs | 31 +- src/librustc_target/abi/call/msp430.rs | 16 +- src/librustc_target/abi/call/nvptx.rs | 16 +- src/librustc_target/abi/call/nvptx64.rs | 16 +- src/librustc_target/abi/call/powerpc.rs | 45 +- src/librustc_target/abi/call/powerpc64.rs | 27 +- src/librustc_target/abi/call/riscv.rs | 16 +- src/librustc_target/abi/call/s390x.rs | 16 +- src/librustc_target/abi/call/sparc.rs | 16 +- src/librustc_target/abi/call/sparc64.rs | 27 +- src/librustc_target/abi/call/wasm32.rs | 18 +- .../abi/call/wasm32_bindgen_compat.rs | 16 +- src/librustc_target/abi/call/x86.rs | 38 +- src/librustc_target/abi/call/x86_64.rs | 18 +- src/librustc_target/abi/call/x86_win64.rs | 12 +- src/librustc_target/abi/mod.rs | 91 +- src/librustc_target/lib.rs | 6 + .../spec/aarch64_pc_windows_msvc.rs | 1 + src/librustc_target/spec/abi.rs | 5 +- .../spec/hermit_kernel_base.rs | 27 + .../spec/i686_unknown_dragonfly.rs | 23 - src/librustc_target/spec/i686_unknown_uefi.rs | 2 +- src/librustc_target/spec/mod.rs | 23 +- .../spec/riscv32i_unknown_none_elf.rs | 2 +- .../spec/riscv32imc_unknown_none_elf.rs | 3 +- .../spec/riscv64gc_unknown_linux_gnu.rs | 25 + .../thumbv7neon_unknown_linux_musleabihf.rs | 37 + src/librustc_target/spec/wasm32_base.rs | 3 + src/librustc_target/spec/windows_base.rs | 27 - .../spec/x86_64_fortanix_unknown_sgx.rs | 52 +- .../spec/x86_64_unknown_hermit_kernel.rs | 25 + src/librustc_traits/Cargo.toml | 3 +- src/librustc_traits/chalk_context/mod.rs | 20 +- .../chalk_context/program_clauses/builtin.rs | 4 +- .../chalk_context/resolvent_ops.rs | 7 +- src/librustc_traits/dropck_outlives.rs | 3 +- src/librustc_traits/generic_types.rs | 2 +- src/librustc_typeck/Cargo.toml | 3 +- src/librustc_typeck/astconv.rs | 58 +- src/librustc_typeck/check/_match.rs | 12 +- src/librustc_typeck/check/autoderef.rs | 2 + src/librustc_typeck/check/callee.rs | 11 +- src/librustc_typeck/check/cast.rs | 19 +- src/librustc_typeck/check/closure.rs | 6 +- src/librustc_typeck/check/coercion.rs | 54 +- src/librustc_typeck/check/compare_method.rs | 16 +- src/librustc_typeck/check/demand.rs | 74 +- src/librustc_typeck/check/dropck.rs | 2 + src/librustc_typeck/check/expr.rs | 165 +- src/librustc_typeck/check/intrinsic.rs | 44 +- src/librustc_typeck/check/method/confirm.rs | 10 +- src/librustc_typeck/check/method/probe.rs | 18 +- src/librustc_typeck/check/method/suggest.rs | 12 +- src/librustc_typeck/check/mod.rs | 584 +- src/librustc_typeck/check/op.rs | 12 +- src/librustc_typeck/check/pat.rs | 149 +- src/librustc_typeck/check/regionck.rs | 271 +- src/librustc_typeck/check/upvar.rs | 249 +- src/librustc_typeck/check/wfcheck.rs | 109 +- src/librustc_typeck/check/writeback.rs | 17 +- src/librustc_typeck/coherence/builtin.rs | 4 +- .../coherence/inherent_impls.rs | 6 +- .../coherence/inherent_impls_overlap.rs | 2 + src/librustc_typeck/coherence/mod.rs | 2 + src/librustc_typeck/coherence/orphan.rs | 66 +- src/librustc_typeck/coherence/unsafety.rs | 6 +- src/librustc_typeck/collect.rs | 207 +- .../constrained_generic_params.rs | 3 +- src/librustc_typeck/error_codes.rs | 5082 ----- .../expr_use_visitor.rs | 201 +- src/librustc_typeck/impl_wf_check.rs | 2 + src/librustc_typeck/lib.rs | 9 +- src/librustc_typeck/mem_categorization.rs | 707 + src/librustc_typeck/outlives/test.rs | 2 + src/librustc_typeck/structured_errors.rs | 2 + src/librustc_typeck/variance/constraints.rs | 4 +- src/librustc_typeck/variance/test.rs | 2 + src/librustdoc/Cargo.toml | 2 + src/librustdoc/clean/auto_trait.rs | 16 +- src/librustdoc/clean/cfg.rs | 10 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 2151 +-- src/librustdoc/clean/types.rs | 1545 ++ src/librustdoc/clean/utils.rs | 585 + src/librustdoc/config.rs | 216 +- src/librustdoc/core.rs | 442 +- src/librustdoc/externalfiles.rs | 2 +- src/librustdoc/html/format.rs | 11 + src/librustdoc/html/highlight.rs | 8 +- src/librustdoc/html/item_type.rs | 12 + src/librustdoc/html/layout.rs | 13 +- src/librustdoc/html/markdown.rs | 4 +- src/librustdoc/html/render.rs | 382 +- src/librustdoc/html/render/cache.rs | 34 +- src/librustdoc/html/static/main.js | 273 +- src/librustdoc/html/static/rustdoc.css | 4 +- src/librustdoc/html/static/settings.css | 14 + src/librustdoc/html/static/storage.js | 4 - src/librustdoc/html/static/themes/dark.css | 7 + src/librustdoc/html/static/themes/light.css | 7 + src/librustdoc/html/static_files.rs | 2 +- src/librustdoc/lib.rs | 431 +- src/librustdoc/markdown.rs | 2 +- .../passes/calculate_doc_coverage.rs | 38 +- .../passes/check_code_block_syntax.rs | 10 +- src/librustdoc/passes/collapse_docs.rs | 22 +- .../passes/collect_intra_doc_links.rs | 584 +- src/librustdoc/passes/collect_trait_impls.rs | 35 +- src/librustdoc/passes/mod.rs | 136 +- .../passes/private_items_doc_tests.rs | 6 +- src/librustdoc/passes/propagate_doc_cfg.rs | 4 +- src/librustdoc/passes/strip_hidden.rs | 6 +- src/librustdoc/passes/strip_priv_imports.rs | 6 +- src/librustdoc/passes/strip_private.rs | 6 +- src/librustdoc/passes/unindent_comments.rs | 47 +- src/librustdoc/test.rs | 27 +- src/librustdoc/theme.rs | 1 + src/librustdoc/visit_ast.rs | 4 +- src/libserialize/Cargo.toml | 2 +- src/libstd/Cargo.toml | 2 +- src/libstd/ascii.rs | 2 +- src/libstd/backtrace.rs | 4 +- .../hash/bench.rs => benches/hash/map.rs} | 15 +- src/libstd/benches/hash/mod.rs | 2 + src/libstd/benches/hash/set_ops.rs | 42 + src/libstd/benches/lib.rs | 5 + src/libstd/build.rs | 2 - src/libstd/collections/hash/mod.rs | 1 - src/libstd/collections/hash/set.rs | 2 +- src/libstd/collections/mod.rs | 12 +- src/libstd/env.rs | 171 +- src/libstd/error.rs | 96 +- src/libstd/f32.rs | 128 +- src/libstd/f64.rs | 144 +- src/libstd/ffi/c_str.rs | 4 +- src/libstd/ffi/mod.rs | 18 +- src/libstd/ffi/os_str.rs | 8 + src/libstd/fs.rs | 348 +- src/libstd/future.rs | 46 +- src/libstd/io/buffered.rs | 156 +- src/libstd/io/error.rs | 65 +- src/libstd/io/impls.rs | 64 +- src/libstd/io/mod.rs | 223 +- src/libstd/io/prelude.rs | 2 +- src/libstd/io/util.rs | 52 +- src/libstd/keyword_docs.rs | 82 +- src/libstd/lib.rs | 7 +- src/libstd/macros.rs | 55 +- src/libstd/net/addr.rs | 91 +- src/libstd/net/ip.rs | 12 +- src/libstd/net/parser.rs | 90 +- src/libstd/net/tcp.rs | 252 +- src/libstd/net/test.rs | 29 +- src/libstd/net/udp.rs | 72 +- src/libstd/num.rs | 119 +- src/libstd/os/android/fs.rs | 13 +- src/libstd/os/android/mod.rs | 2 +- src/libstd/os/android/raw.rs | 26 +- src/libstd/os/dragonfly/fs.rs | 13 +- src/libstd/os/dragonfly/mod.rs | 2 +- src/libstd/os/dragonfly/raw.rs | 39 +- src/libstd/os/emscripten/fs.rs | 13 +- src/libstd/os/emscripten/mod.rs | 2 +- src/libstd/os/emscripten/raw.rs | 36 +- src/libstd/os/fortanix_sgx/mod.rs | 19 +- src/libstd/os/freebsd/fs.rs | 13 +- src/libstd/os/freebsd/mod.rs | 2 +- src/libstd/os/freebsd/raw.rs | 39 +- src/libstd/os/fuchsia/mod.rs | 2 +- src/libstd/os/fuchsia/raw.rs | 117 +- src/libstd/os/haiku/fs.rs | 13 +- src/libstd/os/haiku/mod.rs | 2 +- src/libstd/os/haiku/raw.rs | 32 +- src/libstd/os/ios/fs.rs | 13 +- src/libstd/os/ios/mod.rs | 2 +- src/libstd/os/ios/raw.rs | 36 +- src/libstd/os/linux/fs.rs | 10 +- src/libstd/os/linux/mod.rs | 2 +- src/libstd/os/linux/raw.rs | 147 +- src/libstd/os/macos/fs.rs | 13 +- src/libstd/os/macos/mod.rs | 2 +- src/libstd/os/macos/raw.rs | 36 +- src/libstd/os/mod.rs | 47 +- src/libstd/os/netbsd/fs.rs | 13 +- src/libstd/os/netbsd/mod.rs | 2 +- src/libstd/os/netbsd/raw.rs | 41 +- src/libstd/os/openbsd/fs.rs | 13 +- src/libstd/os/openbsd/mod.rs | 2 +- src/libstd/os/openbsd/raw.rs | 39 +- src/libstd/os/raw/mod.rs | 170 +- src/libstd/os/redox/fs.rs | 13 +- src/libstd/os/redox/mod.rs | 2 +- src/libstd/os/redox/raw.rs | 42 +- src/libstd/os/solaris/fs.rs | 13 +- src/libstd/os/solaris/mod.rs | 2 +- src/libstd/os/solaris/raw.rs | 43 +- src/libstd/os/vxworks/mod.rs | 2 +- src/libstd/os/vxworks/raw.rs | 2 +- src/libstd/panic.rs | 45 +- src/libstd/panicking.rs | 52 +- src/libstd/path.rs | 1628 +- src/libstd/prelude/v1.rs | 58 +- src/libstd/process.rs | 248 +- src/libstd/rt.rs | 26 +- src/libstd/sync/barrier.rs | 22 +- src/libstd/sync/mpsc/blocking.rs | 17 +- src/libstd/sync/mpsc/cache_aligned.rs | 14 +- src/libstd/sync/mpsc/mod.rs | 510 +- src/libstd/sync/mpsc/mpsc_queue.rs | 28 +- src/libstd/sync/mpsc/oneshot.rs | 56 +- src/libstd/sync/mpsc/shared.rs | 57 +- src/libstd/sync/mpsc/spsc_queue.rs | 47 +- src/libstd/sync/mpsc/stream.rs | 112 +- src/libstd/sync/mpsc/sync.rs | 121 +- src/libstd/sync/mutex.rs | 22 +- src/libstd/sync/once.rs | 292 +- src/libstd/sync/rwlock.rs | 28 +- src/libstd/sys/cloudabi/os.rs | 4 +- src/libstd/sys/cloudabi/shims/fs.rs | 2 +- src/libstd/sys/cloudabi/shims/mod.rs | 7 +- src/libstd/sys/cloudabi/shims/net.rs | 4 +- src/libstd/sys/cloudabi/shims/process.rs | 4 +- src/libstd/sys/cloudabi/thread.rs | 10 +- src/libstd/sys/cloudabi/time.rs | 30 +- src/libstd/sys/hermit/alloc.rs | 6 +- src/libstd/sys/hermit/args.rs | 45 +- src/libstd/sys/hermit/cmath.rs | 2 +- src/libstd/sys/hermit/condvar.rs | 4 +- src/libstd/sys/hermit/fd.rs | 10 +- src/libstd/sys/hermit/fs.rs | 84 +- src/libstd/sys/hermit/mod.rs | 46 +- src/libstd/sys/hermit/mutex.rs | 6 +- src/libstd/sys/hermit/net.rs | 19 +- src/libstd/sys/hermit/os.rs | 49 +- src/libstd/sys/hermit/path.rs | 2 +- src/libstd/sys/hermit/pipe.rs | 5 +- src/libstd/sys/hermit/process.rs | 29 +- src/libstd/sys/hermit/rwlock.rs | 6 +- src/libstd/sys/hermit/stack_overflow.rs | 6 +- src/libstd/sys/hermit/stdio.rs | 17 +- src/libstd/sys/hermit/thread.rs | 42 +- src/libstd/sys/hermit/thread_local.rs | 11 +- src/libstd/sys/hermit/time.rs | 45 +- src/libstd/sys/mod.rs | 4 +- src/libstd/sys/sgx/abi/entry.S | 30 + src/libstd/sys/sgx/abi/mod.rs | 18 +- src/libstd/sys/sgx/abi/panic.rs | 12 +- src/libstd/sys/sgx/abi/reloc.rs | 12 +- src/libstd/sys/sgx/abi/thread.rs | 4 +- src/libstd/sys/sgx/abi/tls.rs | 29 +- src/libstd/sys/sgx/abi/usercalls/alloc.rs | 99 +- src/libstd/sys/sgx/abi/usercalls/mod.rs | 67 +- src/libstd/sys/sgx/abi/usercalls/raw.rs | 32 +- src/libstd/sys/sgx/args.rs | 13 +- src/libstd/sys/sgx/cmath.rs | 2 +- src/libstd/sys/sgx/ext/io.rs | 10 +- src/libstd/sys/sgx/ext/mod.rs | 2 +- src/libstd/sys/sgx/fd.rs | 10 +- src/libstd/sys/sgx/fs.rs | 28 +- src/libstd/sys/sgx/net.rs | 81 +- src/libstd/sys/sgx/os.rs | 27 +- src/libstd/sys/sgx/path.rs | 2 +- src/libstd/sys/sgx/process.rs | 29 +- src/libstd/sys/sgx/stack_overflow.rs | 6 +- src/libstd/sys/sgx/stdio.rs | 14 +- src/libstd/sys/sgx/thread.rs | 16 +- src/libstd/sys/sgx/thread_local.rs | 4 +- src/libstd/sys/sgx/time.rs | 5 +- src/libstd/sys/unix/alloc.rs | 20 +- src/libstd/sys/unix/android.rs | 51 +- src/libstd/sys/unix/args.rs | 36 +- src/libstd/sys/unix/cmath.rs | 4 +- src/libstd/sys/unix/ext/fs.rs | 112 +- src/libstd/sys/unix/ext/io.rs | 26 +- src/libstd/sys/unix/ext/mod.rs | 6 +- src/libstd/sys/unix/ext/net.rs | 434 +- src/libstd/sys/unix/ext/process.rs | 31 +- src/libstd/sys/unix/ext/raw.rs | 25 +- src/libstd/sys/unix/fast_thread_local.rs | 42 +- src/libstd/sys/unix/fd.rs | 131 +- src/libstd/sys/unix/fs.rs | 4 +- src/libstd/sys/unix/io.rs | 24 +- src/libstd/sys/unix/l4re.rs | 74 +- src/libstd/sys/unix/memchr.rs | 23 +- src/libstd/sys/unix/mod.rs | 30 +- src/libstd/sys/unix/net.rs | 112 +- src/libstd/sys/unix/path.rs | 2 +- src/libstd/sys/unix/pipe.rs | 38 +- src/libstd/sys/unix/process/process_common.rs | 93 +- .../sys/unix/process/process_fuchsia.rs | 102 +- src/libstd/sys/unix/process/process_unix.rs | 4 +- src/libstd/sys/unix/process/zircon.rs | 173 +- src/libstd/sys/unix/rand.rs | 64 +- src/libstd/sys/unix/stack_overflow.rs | 87 +- src/libstd/sys/unix/stdio.rs | 14 +- src/libstd/sys/unix/thread.rs | 172 +- src/libstd/sys/unix/thread_local.rs | 2 +- src/libstd/sys/unix/weak.rs | 6 +- src/libstd/sys/vxworks/alloc.rs | 10 +- src/libstd/sys/vxworks/args.rs | 47 +- src/libstd/sys/vxworks/cmath.rs | 4 +- src/libstd/sys/vxworks/condvar.rs | 19 +- src/libstd/sys/vxworks/ext/fs.rs | 98 +- src/libstd/sys/vxworks/ext/io.rs | 40 +- src/libstd/sys/vxworks/ext/mod.rs | 20 +- src/libstd/sys/vxworks/ext/process.rs | 13 +- src/libstd/sys/vxworks/fast_thread_local.rs | 2 +- src/libstd/sys/vxworks/fd.rs | 81 +- src/libstd/sys/vxworks/fs.rs | 216 +- src/libstd/sys/vxworks/io.rs | 24 +- src/libstd/sys/vxworks/memchr.rs | 9 +- src/libstd/sys/vxworks/mod.rs | 22 +- src/libstd/sys/vxworks/mutex.rs | 12 +- src/libstd/sys/vxworks/net.rs | 113 +- src/libstd/sys/vxworks/os.rs | 22 +- src/libstd/sys/vxworks/path.rs | 2 +- src/libstd/sys/vxworks/pipe.rs | 35 +- src/libstd/sys/vxworks/process/mod.rs | 2 +- .../sys/vxworks/process/process_common.rs | 58 +- .../sys/vxworks/process/process_vxworks.rs | 12 +- src/libstd/sys/vxworks/rand.rs | 7 +- src/libstd/sys/vxworks/rwlock.rs | 18 +- src/libstd/sys/vxworks/stack_overflow.rs | 13 +- src/libstd/sys/vxworks/stdio.rs | 12 +- src/libstd/sys/vxworks/thread.rs | 43 +- src/libstd/sys/vxworks/thread_local.rs | 2 +- src/libstd/sys/vxworks/time.rs | 81 +- src/libstd/sys/vxworks/weak.rs | 8 +- src/libstd/sys/wasi/alloc.rs | 2 +- src/libstd/sys/wasi/args.rs | 40 +- src/libstd/sys/wasi/ext/fs.rs | 117 +- src/libstd/sys/wasi/ext/io.rs | 8 +- src/libstd/sys/wasi/ext/mod.rs | 18 +- src/libstd/sys/wasi/fd.rs | 122 +- src/libstd/sys/wasi/fs.rs | 220 +- src/libstd/sys/wasi/io.rs | 15 +- src/libstd/sys/wasi/mod.rs | 44 +- src/libstd/sys/wasi/net.rs | 55 +- src/libstd/sys/wasi/os.rs | 42 +- src/libstd/sys/wasi/path.rs | 2 +- src/libstd/sys/wasi/pipe.rs | 5 +- src/libstd/sys/wasi/process.rs | 31 +- src/libstd/sys/wasi/stdio.rs | 25 +- src/libstd/sys/wasi/thread.rs | 52 +- src/libstd/sys/wasi/time.rs | 23 +- src/libstd/sys/wasm/alloc.rs | 4 +- src/libstd/sys/wasm/args.rs | 8 +- src/libstd/sys/wasm/cmath.rs | 2 +- src/libstd/sys/wasm/condvar_atomics.rs | 2 +- src/libstd/sys/wasm/fast_thread_local.rs | 2 +- src/libstd/sys/wasm/fs.rs | 28 +- src/libstd/sys/wasm/mutex_atomics.rs | 4 +- src/libstd/sys/wasm/net.rs | 21 +- src/libstd/sys/wasm/os.rs | 6 +- src/libstd/sys/wasm/path.rs | 2 +- src/libstd/sys/wasm/pipe.rs | 5 +- src/libstd/sys/wasm/process.rs | 29 +- src/libstd/sys/wasm/stack_overflow.rs | 6 +- src/libstd/sys/wasm/thread.rs | 16 +- src/libstd/sys/wasm/thread_local.rs | 2 +- src/libstd/sys/wasm/time.rs | 3 +- src/libstd/sys/windows/alloc.rs | 16 +- src/libstd/sys/windows/args.rs | 56 +- src/libstd/sys/windows/cmath.rs | 6 +- src/libstd/sys/windows/compat.rs | 3 +- src/libstd/sys/windows/ext/ffi.rs | 4 +- src/libstd/sys/windows/ext/fs.rs | 65 +- src/libstd/sys/windows/ext/io.rs | 6 +- src/libstd/sys/windows/ext/mod.rs | 23 +- src/libstd/sys/windows/ext/process.rs | 4 +- src/libstd/sys/windows/ext/raw.rs | 9 +- src/libstd/sys/windows/ext/thread.rs | 6 +- src/libstd/sys/windows/fs.rs | 361 +- src/libstd/sys/windows/handle.rs | 104 +- src/libstd/sys/windows/io.rs | 17 +- src/libstd/sys/windows/net.rs | 4 +- src/libstd/sys/windows/os.rs | 144 +- src/libstd/sys/windows/os_str.rs | 14 +- src/libstd/sys/windows/path.rs | 9 +- src/libstd/sys/windows/pipe.rs | 99 +- src/libstd/sys/windows/rand.rs | 23 +- src/libstd/sys/windows/stack_overflow.rs | 5 +- src/libstd/sys/windows/stdio.rs | 72 +- src/libstd/sys/windows/stdio_uwp.rs | 7 +- src/libstd/sys/windows/thread.rs | 54 +- src/libstd/sys/windows/thread_local.rs | 25 +- src/libstd/sys_common/alloc.rs | 30 +- src/libstd/sys_common/backtrace.rs | 9 +- src/libstd/sys_common/bytestring.rs | 4 +- src/libstd/sys_common/fs.rs | 14 +- src/libstd/sys_common/io.rs | 2 +- src/libstd/sys_common/mod.rs | 2 +- src/libstd/sys_common/net.rs | 256 +- src/libstd/sys_common/os_str_bytes.rs | 17 +- src/libstd/sys_common/poison.rs | 44 +- src/libstd/sys_common/process.rs | 14 +- src/libstd/sys_common/thread_info.rs | 28 +- src/libstd/sys_common/util.rs | 10 +- src/libstd/sys_common/wtf8.rs | 243 +- src/libstd/tests/env.rs | 15 +- src/libstd/thread/local.rs | 107 +- src/libstd/thread/mod.rs | 12 + src/libsyntax/Cargo.toml | 7 +- src/libsyntax/ast.rs | 578 +- src/libsyntax/attr/builtin.rs | 300 +- src/libsyntax/attr/mod.rs | 220 +- src/libsyntax/diagnostics/macros.rs | 24 +- src/libsyntax/early_buffered_lints.rs | 40 +- src/libsyntax/error_codes.rs | 545 - src/libsyntax/expand/allocator.rs | 6 +- src/libsyntax/expand/mod.rs | 10 - src/libsyntax/feature_gate/check.rs | 293 +- src/libsyntax/feature_gate/mod.rs | 64 - src/libsyntax/lib.rs | 31 +- src/libsyntax/mut_visit.rs | 118 +- src/libsyntax/print/pprust.rs | 200 +- src/libsyntax/print/pprust/tests.rs | 8 +- src/libsyntax/{parse => }/token.rs | 79 +- src/libsyntax/tokenstream.rs | 57 +- src/libsyntax/{parse => util}/classify.rs | 0 .../{parse/lexer => util}/comments.rs | 25 +- .../{parse/lexer => util}/comments/tests.rs | 0 src/libsyntax/util/lev_distance.rs | 2 +- src/libsyntax/{parse => util}/literal.rs | 39 +- src/libsyntax/util/parser.rs | 6 +- src/libsyntax/visit.rs | 37 +- src/libsyntax_expand/Cargo.toml | 9 +- src/libsyntax_expand/base.rs | 37 +- src/libsyntax_expand/build.rs | 6 +- src/libsyntax_expand/expand.rs | 115 +- src/libsyntax_expand/lib.rs | 29 + src/libsyntax_expand/mbe.rs | 26 +- src/libsyntax_expand/mbe/macro_check.rs | 9 +- src/libsyntax_expand/mbe/macro_parser.rs | 37 +- src/libsyntax_expand/mbe/macro_rules.rs | 56 +- src/libsyntax_expand/mbe/quoted.rs | 2 +- src/libsyntax_expand/mbe/transcribe.rs | 21 +- .../mut_visit/tests.rs | 11 +- .../parse/lexer/tests.rs | 21 +- .../parse/tests.rs | 60 +- src/libsyntax_expand/placeholders.rs | 9 +- src/libsyntax_expand/proc_macro.rs | 114 +- src/libsyntax_expand/proc_macro_server.rs | 17 +- src/{libsyntax => libsyntax_expand}/tests.rs | 18 +- .../tokenstream/tests.rs | 10 +- src/libsyntax_ext/Cargo.toml | 5 +- src/libsyntax_ext/asm.rs | 40 +- src/libsyntax_ext/assert.rs | 32 +- src/libsyntax_ext/cfg.rs | 2 +- src/libsyntax_ext/cmdline_attrs.rs | 8 +- src/libsyntax_ext/concat.rs | 3 +- src/libsyntax_ext/concat_idents.rs | 2 +- src/libsyntax_ext/deriving/clone.rs | 3 +- src/libsyntax_ext/deriving/cmp/eq.rs | 3 - src/libsyntax_ext/deriving/cmp/partial_eq.rs | 3 - src/libsyntax_ext/deriving/default.rs | 2 + src/libsyntax_ext/deriving/generic/mod.rs | 48 +- src/libsyntax_ext/env.rs | 2 +- src/libsyntax_ext/error_codes.rs | 120 - src/libsyntax_ext/format.rs | 99 +- src/libsyntax_ext/format_foreign.rs | 6 +- src/libsyntax_ext/global_allocator.rs | 15 +- src/libsyntax_ext/global_asm.rs | 2 +- src/libsyntax_ext/lib.rs | 4 +- src/libsyntax_ext/plugin_macro_defs.rs | 58 - src/libsyntax_ext/proc_macro_harness.rs | 26 +- src/libsyntax_ext/source_util.rs | 23 +- src/libsyntax_ext/test.rs | 14 +- src/libsyntax_ext/test_harness.rs | 12 +- src/libsyntax_ext/util.rs | 5 +- src/libsyntax_pos/Cargo.toml | 1 + .../caching_source_map_view.rs | 4 +- src/libsyntax_pos/edition.rs | 5 +- src/libsyntax_pos/fatal_error.rs | 30 + src/libsyntax_pos/hygiene.rs | 37 +- src/libsyntax_pos/lib.rs | 111 +- .../source_map.rs | 81 +- .../source_map/tests.rs | 0 src/libsyntax_pos/symbol.rs | 150 +- src/libterm/terminfo/mod.rs | 2 +- src/libtest/cli.rs | 4 + src/libtest/lib.rs | 15 +- src/libtest/test_result.rs | 32 +- src/libtest/tests.rs | 52 +- src/rustc/Cargo.toml | 1 + src/rustllvm/PassWrapper.cpp | 126 +- src/rustllvm/RustWrapper.cpp | 47 +- src/stage0.txt | 6 +- src/test/codegen/abi-efiapi.rs | 6 +- src/test/codegen/align-enum.rs | 1 - src/test/codegen/align-struct.rs | 1 - src/test/codegen/bool-cmp.rs | 17 + src/test/codegen/consts.rs | 1 - src/test/codegen/function-arguments.rs | 4 +- src/test/codegen/gdb_debug_script_load.rs | 2 + src/test/codegen/match.rs | 8 +- src/test/codegen/optimize-attr-1.rs | 6 +- src/test/codegen/packed.rs | 1 - src/test/codegen/repeat-trusted-len.rs | 1 - .../codegen/sanitizer-memory-track-orgins.rs | 28 + src/test/codegen/sanitizer-recover.rs | 34 + src/test/codegen/set-discriminant-invalid.rs | 43 + .../simd-intrinsic-float-minmax.rs | 2 - src/test/codegen/stores.rs | 1 - src/test/codegen/try_identity.rs | 17 + src/test/compile-fail/consts/const-err3.rs | 1 - .../compile-fail/consts/const-fn-error.rs | 6 +- src/test/compile-fail/issue-52443.rs | 9 +- .../debuginfo/pretty-std-collections-hash.rs | 97 + src/test/incremental/delayed_span_bug.rs | 8 + src/test/incremental/hashes/for_loops.rs | 2 +- .../incremental/hashes/let_expressions.rs | 8 +- .../incremental/hashes/loop_expressions.rs | 2 +- .../incremental/hashes/struct_constructors.rs | 4 +- .../incremental/hashes/while_let_loops.rs | 10 +- src/test/incremental/hashes/while_loops.rs | 4 +- ...ssue-59523-on-implemented-is-not-unused.rs | 2 +- src/test/incremental/issue-61323.rs | 15 + src/test/incremental/warnings-reemitted.rs | 3 +- src/test/mir-opt/box_expr.rs | 1 + .../mir-opt/const-promotion-extern-static.rs | 71 + .../const_prop/const_prop_fails_gracefully.rs | 6 +- src/test/mir-opt/const_prop/issue-66971.rs | 38 + src/test/mir-opt/const_prop/issue-67019.rs | 34 + .../const_prop/read_immutable_static.rs | 12 +- src/test/mir-opt/const_prop/ref_deref.rs | 2 +- src/test/mir-opt/const_prop/reify_fn_ptr.rs | 2 +- src/test/mir-opt/const_prop/return_place.rs | 48 + src/test/mir-opt/const_prop/slice_len.rs | 4 +- .../mir-opt/generator-storage-dead-unwind.rs | 2 + src/test/mir-opt/graphviz.rs | 10 +- .../mir-opt/inline-closure-borrows-arg.rs | 56 +- src/test/mir-opt/inline-closure-captures.rs | 60 + src/test/mir-opt/inline-closure.rs | 52 +- src/test/mir-opt/issue-41110.rs | 5 + src/test/mir-opt/issue-41888.rs | 4 +- src/test/mir-opt/issue-49232.rs | 1 + src/test/mir-opt/match-arm-scopes.rs | 6 + src/test/mir-opt/match_false_edges.rs | 12 +- .../mir-opt/nll/region-subtyping-basic.rs | 4 + .../mir-opt/packed-struct-drop-aligned.rs | 1 + src/test/mir-opt/retag.rs | 2 +- src/test/mir-opt/retain-never-const.rs | 29 + src/test/mir-opt/simplify-arm-identity.rs | 75 + src/test/mir-opt/simplify_try.rs | 223 + .../mir-opt/storage_live_dead_in_statics.rs | 4 +- src/test/mir-opt/uniform_array_move_out.rs | 56 +- .../mir-opt/uninhabited_enum_branching.rs | 224 + src/test/pretty/enum-variant-vis.rs | 8 + src/test/pretty/issue-4264.pp | 56 +- .../emit-stack-sizes/Makefile | 1 - .../extern-flag-fun/Makefile | 4 +- .../extern-flag-fun/gated_unstable.rs | 3 + .../extern-flag-fun/rustc.rs | 1 + .../extern-flag-pathless/Makefile | 18 + .../extern-flag-pathless/bar-dynamic.rs | 3 + .../extern-flag-pathless/bar-static.rs | 3 + .../extern-flag-pathless/foo.rs | 3 + .../glibc-staticlib-args/Makefile | 12 + .../glibc-staticlib-args/library.rs | 4 + .../glibc-staticlib-args/program.c | 7 + .../invalid-library/Makefile | 4 +- src/test/run-make-fulldeps/issue-19371/foo.rs | 11 +- .../long-linker-command-lines/foo.rs | 73 +- .../pgo-branch-weights/Makefile | 35 + .../pgo-branch-weights/filecheck-patterns.txt | 24 + .../pgo-branch-weights/interesting.rs | 40 + .../pgo-branch-weights/main.rs | 17 + .../pgo-branch-weights/opaque.rs | 6 + .../pgo-indirect-call-promotion/Makefile | 36 + .../filecheck-patterns.txt | 16 + .../interesting.rs | 56 + .../pgo-indirect-call-promotion/main.rs | 14 + .../pgo-indirect-call-promotion/opaque.rs | 7 + .../pretty-print-path-suffix/Makefile | 9 - .../pretty-print-path-suffix/foo.pp | 5 - .../pretty-print-path-suffix/foo_method.pp | 7 - .../pretty-print-path-suffix/input.rs | 18 - .../pretty-print-path-suffix/nest_foo.pp | 4 - .../reproducible-build-2/Makefile | 1 + .../run-make-fulldeps/rustdoc-themes/Makefile | 10 + .../run-make-fulldeps/rustdoc-themes/foo.rs | 4 + .../save-analysis-rfc2126/Makefile | 3 +- .../sysroot-crates-are-unstable/test.py | 2 +- src/test/run-make-fulldeps/tools.mk | 2 +- .../deny-intra-link-resolution-failure.stderr | 2 +- .../rustdoc-ui/doc-test-rustdoc-feature.rs | 6 +- src/test/rustdoc-ui/doc-without-codeblock.rs | 8 +- .../rustdoc-ui/doc-without-codeblock.stderr | 8 +- .../failed-doctest-missing-codes.stdout | 7 +- .../rustdoc-ui/intra-doc-alias-ice.stderr | 2 +- .../rustdoc-ui/intra-link-span-ice-55723.rs | 2 +- .../intra-link-span-ice-55723.stderr | 2 +- src/test/rustdoc-ui/intra-links-anchors.rs | 45 + .../rustdoc-ui/intra-links-anchors.stderr | 32 + .../rustdoc-ui/intra-links-warning-crlf.rs | 7 +- .../intra-links-warning-crlf.stderr | 14 +- src/test/rustdoc-ui/intra-links-warning.rs | 33 +- .../rustdoc-ui/intra-links-warning.stderr | 72 +- src/test/rustdoc-ui/invalid-syntax.rs | 13 +- src/test/rustdoc-ui/invalid-syntax.stderr | 84 +- src/test/rustdoc-ui/issue-61732.rs | 4 + src/test/rustdoc-ui/issue-61732.stderr | 11 + src/test/rustdoc-ui/lint-group.rs | 4 +- src/test/rustdoc-ui/lint-group.stderr | 6 +- .../lint-missing-doc-code-example.stderr | 4 +- src/test/rustdoc-ui/private-item-doc-test.rs | 2 +- .../rustdoc-ui/private-item-doc-test.stderr | 2 +- src/test/rustdoc/auxiliary/issue-66159-1.rs | 2 + src/test/rustdoc/const-display.rs | 6 +- src/test/rustdoc/duplicate-cfg.rs | 15 + src/test/rustdoc/edition-flag.rs | 2 +- src/test/rustdoc/inline_cross/use_crate.rs | 2 +- .../intra-doc-link-enum-struct-field.rs | 14 + src/test/rustdoc/intra-links-anchors.rs | 12 + src/test/rustdoc/issue-46380.rs | 5 - src/test/rustdoc/issue-66159.rs | 10 + src/test/rustdoc/issue-67851-both.rs | 8 + src/test/rustdoc/issue-67851-hidden.rs | 8 + src/test/rustdoc/issue-67851-neither.rs | 6 + src/test/rustdoc/issue-67851-private.rs | 8 + src/test/ui-fulldeps/ast_stmt_expr_attr.rs | 28 +- .../ui-fulldeps/auxiliary/attr-plugin-test.rs | 23 - .../ui-fulldeps/auxiliary/empty-plugin.rs | 10 + .../auxiliary/issue-40001-plugin.rs | 19 +- .../auxiliary/lint-for-crate-rpass.rs | 2 +- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 1 + .../auxiliary/lint-group-plugin-test.rs | 4 +- .../ui-fulldeps/auxiliary/lint-plugin-test.rs | 4 +- .../ui-fulldeps/auxiliary/lint-tool-test.rs | 4 +- .../ui-fulldeps/auxiliary/llvm-pass-plugin.rs | 19 - src/test/ui-fulldeps/auxiliary/plugin-args.rs | 43 - .../ui-fulldeps/auxiliary/roman-numerals.rs | 69 - .../feature-gate-plugin.rs | 5 +- .../feature-gate-plugin.stderr | 12 +- src/test/ui-fulldeps/gated-plugin.rs | 4 +- src/test/ui-fulldeps/gated-plugin.stderr | 8 +- .../lint_pass_impl_without_macro.rs | 4 +- .../lint_pass_impl_without_macro.stderr | 4 +- src/test/ui-fulldeps/issue-15778-pass.rs | 12 +- src/test/ui-fulldeps/issue-15778-pass.stderr | 2 +- src/test/ui-fulldeps/issue-40001.rs | 7 +- .../ui-fulldeps/lint-plugin-cmdline-allow.rs | 5 +- .../lint-plugin-cmdline-allow.stderr | 15 +- .../ui-fulldeps/lint-plugin-cmdline-load.rs | 6 +- .../lint-plugin-cmdline-load.stderr | 8 + .../ui-fulldeps/lint-tool-cmdline-allow.rs | 6 +- .../lint-tool-cmdline-allow.stderr | 17 +- src/test/ui-fulldeps/llvm-pass-plugin.rs | 8 - src/test/ui-fulldeps/llvm-pass-plugin.stderr | 8 - src/test/ui-fulldeps/lto-syntax-extension.rs | 2 +- .../macro-crate-multi-decorator.rs | 7 +- .../ui-fulldeps/mod_dir_path_canonicalized.rs | 6 +- .../ui-fulldeps/outlive-expansion-phase.rs | 2 +- .../ui-fulldeps/pathless-extern-unstable.rs | 10 + .../pathless-extern-unstable.stderr | 12 + src/test/ui-fulldeps/plugin-args-1.rs | 10 - src/test/ui-fulldeps/plugin-args-1.stderr | 8 - src/test/ui-fulldeps/plugin-args-2.rs | 10 - src/test/ui-fulldeps/plugin-args-2.stderr | 8 - src/test/ui-fulldeps/plugin-args-3.rs | 10 - src/test/ui-fulldeps/plugin-args-3.stderr | 8 - src/test/ui-fulldeps/plugin-args.rs | 9 + src/test/ui-fulldeps/plugin-args.stderr | 16 + .../ui-fulldeps/plugin-as-extern-crate.rs | 11 +- .../ui-fulldeps/plugin-as-extern-crate.stderr | 14 - .../ui-fulldeps/plugin-attr-register-deny.rs | 21 - .../plugin-attr-register-deny.stderr | 34 - src/test/ui-fulldeps/plugin-reexport.rs | 11 - src/test/ui-fulldeps/plugin-reexport.stderr | 23 - src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 11 +- src/test/ui-fulldeps/roman-numerals-macro.rs | 15 - .../ui-fulldeps/roman-numerals-macro.stderr | 8 - src/test/ui/allocator/two-allocators.stderr | 11 +- src/test/ui/allocator/two-allocators3.stderr | 2 +- src/test/ui/anon-params-denied-2018.stderr | 8 +- .../anonymous-higher-ranked-lifetime.stderr | 1 + src/test/ui/arg-type-mismatch.stderr | 5 +- src/test/ui/array-break-length.stderr | 12 +- src/test/ui/array-not-vector.rs | 10 +- src/test/ui/array-not-vector.stderr | 17 +- src/test/ui/asm/asm-bad-clobber.stderr | 1 + src/test/ui/asm/asm-in-bad-modifier.stderr | 2 + src/test/ui/asm/asm-literal-escaping.rs | 12 + src/test/ui/asm/asm-out-no-modifier.stderr | 1 + src/test/ui/asm/asm-parse-errors.stderr | 10 +- src/test/ui/asm/issue-51431.stderr | 1 + ...ssociated-const-generic-obligations.stderr | 6 +- ...ssociated-const-impl-wrong-lifetime.stderr | 4 +- .../associated-const-impl-wrong-type.stderr | 2 +- src/test/ui/associated-const/issue-63496.rs | 4 +- .../ui/associated-const/issue-63496.stderr | 12 +- .../ui/associated-item/issue-48027.stderr | 6 +- .../ui/associated-type-bounds/dyn-lcsit.rs | 2 +- .../implied-region-constraints.nll.stderr | 4 + .../implied-region-constraints.stderr | 1 + src/test/ui/associated-type-bounds/lcsit.rs | 2 +- .../ui/associated-type-bounds/type-alias.rs | 26 +- ...ted-type-projection-from-supertrait.stderr | 12 - ...nding-to-type-defined-in-supertrait.stderr | 6 - .../associated-types/associated-types-eq-3.rs | 8 +- .../associated-types-eq-3.stderr | 17 +- .../associated-types-eq-hr.stderr | 12 +- .../associated-types-in-ambiguous-context.rs | 10 + ...sociated-types-in-ambiguous-context.stderr | 18 +- .../associated-types-issue-20346.stderr | 7 +- ...ated-types-multiple-types-one-trait.stderr | 12 +- ...sociated-types-overridden-binding-2.stderr | 4 +- ...associated-types-overridden-binding.stderr | 17 +- .../associated-types-path-2.rs | 4 +- .../associated-types-path-2.stderr | 6 +- ...es-project-from-hrtb-in-fn-body.nll.stderr | 6 + ...-types-project-from-hrtb-in-fn-body.stderr | 1 + .../associated-types-subtyping-1.nll.stderr | 4 + .../associated-types-subtyping-1.stderr | 1 + .../associated-types-unconstrained.stderr | 6 +- .../bound-lifetime-constrained.rs | 2 +- .../bound-lifetime-in-binding-only.ok.stderr | 2 +- .../bound-lifetime-in-binding-only.rs | 2 +- .../bound-lifetime-in-return-only.ok.stderr | 2 +- .../bound-lifetime-in-return-only.rs | 2 +- ...fn-ret-contravariant.krisskross.nll.stderr | 6 + ...ect-fn-ret-contravariant.krisskross.stderr | 1 + .../project-fn-ret-contravariant.ok.stderr | 2 +- ...project-fn-ret-contravariant.oneuse.stderr | 2 +- .../cache/project-fn-ret-contravariant.rs | 4 +- ...-fn-ret-contravariant.transmute.nll.stderr | 2 + ...ect-fn-ret-invariant.krisskross.nll.stderr | 6 + ...project-fn-ret-invariant.krisskross.stderr | 1 + .../cache/project-fn-ret-invariant.ok.stderr | 2 +- ...project-fn-ret-invariant.oneuse.nll.stderr | 6 + .../project-fn-ret-invariant.oneuse.stderr | 1 + .../cache/project-fn-ret-invariant.rs | 2 +- ...ject-fn-ret-invariant.transmute.nll.stderr | 2 + .../project-fn-ret-invariant.transmute.stderr | 20 +- .../higher-ranked-projection.good.stderr | 2 +- .../higher-ranked-projection.rs | 2 +- .../ui/associated-types/issue-44153.stderr | 4 +- .../point-at-type-on-obligation-failure-2.rs | 16 + ...int-at-type-on-obligation-failure-2.stderr | 28 +- ...point-at-type-on-obligation-failure.stderr | 5 +- src/test/ui/ast-json/ast-json-output.stdout | 2 +- ...block-control-flow-static-semantics.stderr | 30 +- src/test/ui/async-await/async-fn-nonsend.rs | 8 +- .../ui/async-await/async-fn-nonsend.stderr | 91 +- src/test/ui/async-await/async-trait-fn.rs | 7 + src/test/ui/async-await/async-trait-fn.stderr | 21 + .../incorrect-syntax-suggestions.stderr | 2 +- .../dont-suggest-missing-await.stderr | 6 +- .../edition-deny-async-fns-2015.stderr | 6 +- src/test/ui/async-await/issue-61793.rs | 2 +- src/test/ui/async-await/issue-64130-1-sync.rs | 23 + .../ui/async-await/issue-64130-1-sync.stderr | 22 + src/test/ui/async-await/issue-64130-2-send.rs | 23 + .../ui/async-await/issue-64130-2-send.stderr | 22 + .../ui/async-await/issue-64130-3-other.rs | 25 + .../ui/async-await/issue-64130-3-other.stderr | 24 + .../async-await/issue-64130-4-async-move.rs | 28 + .../issue-64130-4-async-move.stderr | 22 + .../issue-64130-non-send-future-diags.rs | 12 +- .../issue-64130-non-send-future-diags.stderr | 11 +- .../issue-66387-if-without-else.stderr | 4 +- .../async-await/issue-67252-unnamed-future.rs | 24 + .../issue-67252-unnamed-future.stderr | 22 + src/test/ui/async-await/issues/issue-53249.rs | 2 +- .../issues/issue-54752-async-block.rs | 1 + src/test/ui/async-await/issues/issue-54974.rs | 2 +- src/test/ui/async-await/issues/issue-60518.rs | 2 +- .../ui/async-await/issues/issue-62009-1.rs | 3 +- .../async-await/issues/issue-62009-1.stderr | 12 +- .../async-await/issues/issue-62097.nll.stderr | 29 + src/test/ui/async-await/issues/issue-62097.rs | 19 + .../ui/async-await/issues/issue-62097.stderr | 16 + .../issues/issue-63388-1.nll.stderr | 4 +- .../async-await/issues/issue-63388-1.stderr | 1 + .../async-await/issues/issue-63388-2.stderr | 4 - .../ui/async-await/issues/issue-64477-2.rs | 22 + ...-65419-async-fn-resume-after-completion.rs | 46 + ...issue-65419-async-fn-resume-after-panic.rs | 52 + ...65419-generator-resume-after-completion.rs | 25 + .../issues/issue-66695-static-refs.rs | 24 + .../issue-66958-non-copy-infered-type-arg.rs | 15 + ...sue-66958-non-copy-infered-type-arg.stderr | 13 + .../issues/issue-67611-static-mut-refs.rs | 33 + .../ret-impl-trait-one.nll.stderr | 2 + .../ret-impl-trait-one.stderr | 1 + src/test/ui/async-await/no-async-const.stderr | 2 +- src/test/ui/async-await/no-const-async.stderr | 5 - .../ui/async-await/no-unsafe-async.stderr | 4 +- .../suggest-missing-await-closure.stderr | 6 +- .../async-await/suggest-missing-await.fixed | 11 + .../ui/async-await/suggest-missing-await.rs | 11 + .../async-await/suggest-missing-await.stderr | 25 +- .../async-await/try-on-option-in-async.stderr | 30 +- .../ui/async-await/unresolved_type_param.rs | 2 +- .../async-await/unresolved_type_param.stderr | 2 +- .../ui/attributes/register-attr-tool-fail.rs | 13 + .../attributes/register-attr-tool-fail.stderr | 42 + .../attributes/register-attr-tool-import.rs | 14 + .../register-attr-tool-import.stderr | 26 + .../attributes/register-attr-tool-prelude.rs | 14 + .../register-attr-tool-prelude.stderr | 15 + .../attributes/register-attr-tool-unused.rs | 10 + .../register-attr-tool-unused.stderr | 33 + src/test/ui/attributes/register-attr-tool.rs | 19 + src/test/ui/bad/bad-const-type.rs | 2 - src/test/ui/bad/bad-const-type.stderr | 3 - src/test/ui/bad/bad-expr-path.stderr | 4 +- src/test/ui/bad/bad-expr-path2.stderr | 4 +- .../bad/bad-intrinsic-monomorphization.stderr | 1 + src/test/ui/bad/bad-main.stderr | 4 +- .../ui/binding/empty-types-in-patterns.rs | 2 +- src/test/ui/binop/binop-consume-args.stderr | 60 +- src/test/ui/binop/binop-logic-float.stderr | 4 +- src/test/ui/binop/binop-logic-int.stderr | 10 +- src/test/ui/binop/binop-move-semantics.stderr | 8 +- .../ui/blind/blind-item-block-middle.stderr | 3 - src/test/ui/block-expr-precedence.rs | 1 + .../block-expression-remove-semicolon.stderr | 5 +- .../block-must-not-have-result-do.stderr | 5 +- .../block-must-not-have-result-res.stderr | 5 +- .../block-must-not-have-result-while.rs | 4 +- .../block-must-not-have-result-while.stderr | 5 +- .../consider-removing-last-semi.stderr | 10 +- src/test/ui/block-result/issue-11714.stderr | 5 +- src/test/ui/block-result/issue-13428.stderr | 10 +- src/test/ui/block-result/issue-13624.rs | 8 +- src/test/ui/block-result/issue-13624.stderr | 12 +- src/test/ui/block-result/issue-20862.stderr | 6 +- src/test/ui/block-result/issue-22645.stderr | 5 +- src/test/ui/block-result/issue-5500.rs | 6 +- src/test/ui/block-result/issue-5500.stderr | 6 +- .../unexpected-return-on-unit.stderr | 4 +- .../borrow-immutable-upvar-mutation.stderr | 3 +- ...k-assign-to-andmut-in-aliasable-loc.stderr | 1 + .../borrowck-assign-to-constants.stderr | 1 + ...orrow-mut-base-ptr-in-aliasable-loc.stderr | 2 +- ...rrowck-borrow-overloaded-auto-deref.stderr | 3 +- .../borrowck-borrow-overloaded-deref.stderr | 3 +- .../borrowck/borrowck-closures-unique.stderr | 2 +- .../ui/borrowck/borrowck-init-in-fru.stderr | 4 +- .../ui/borrowck/borrowck-issue-14498.stderr | 3 +- .../borrowck-move-error-with-note.stderr | 18 +- ...borrowck-move-out-from-array-no-overlap.rs | 69 + ...owck-move-out-from-array-use-no-overlap.rs | 69 + .../borrowck-move-out-from-array-use.rs | 99 + .../borrowck-move-out-from-array-use.stderr | 143 + .../borrowck/borrowck-move-out-from-array.rs | 69 +- .../borrowck-move-out-from-array.stderr | 100 +- .../borrowck-move-out-of-vec-tail.stderr | 8 +- ...borrowck-overloaded-index-ref-index.stderr | 3 +- ...orrow-from-shorter-lived-andmut.nll.stderr | 2 + ...-reborrow-from-shorter-lived-andmut.stderr | 1 + ...e-pattern-element-loan-array-no-overlap.rs | 66 + ...rrowck-slice-pattern-element-loan-array.rs | 60 + ...ck-slice-pattern-element-loan-array.stderr | 86 + ...e-pattern-element-loan-slice-no-overlap.rs | 61 + ...rowck-slice-pattern-element-loan-slice.rs} | 46 - ...k-slice-pattern-element-loan-slice.stderr} | 24 +- .../borrowck/borrowck-unboxed-closures.stderr | 4 +- .../borrowck/borrowck-vec-pattern-nesting.rs | 2 +- .../borrowck-vec-pattern-nesting.stderr | 6 +- src/test/ui/borrowck/index-mut-help.stderr | 3 +- src/test/ui/borrowck/issue-45983.nll.stderr | 1 + ...e-54499-field-mutation-of-moved-out.stderr | 3 +- ...rowck-migrate-scans-parents.migrate.stderr | 3 +- ...-borrowck-migrate-scans-parents.nll.stderr | 3 +- ...-ascribe-wildcard-to-structured-pattern.rs | 2 +- src/test/ui/borrowck/issue-64453.rs | 5 +- src/test/ui/borrowck/issue-64453.stderr | 31 +- .../move-from-union-field-issue-66500.rs | 30 + .../move-from-union-field-issue-66500.stderr | 27 + src/test/ui/borrowck/mutability-errors.stderr | 3 +- ...gnment_immutable_fields_overlapping.stderr | 3 +- ...reassignment_immutable_fields_twice.stderr | 3 +- ...regions-bound-missing-bound-in-impl.stderr | 4 +- .../slice-index-bounds-check-invalidation.rs | 82 + ...ice-index-bounds-check-invalidation.stderr | 35 + src/test/ui/break-while-condition.stderr | 18 +- src/test/ui/c-variadic/variadic-ffi-1.stderr | 16 +- src/test/ui/c-variadic/variadic-ffi-4.stderr | 30 +- src/test/ui/can-begin-expr-check.stderr | 2 +- .../cannot-mutate-captured-non-mut-var.stderr | 3 +- src/test/ui/cfg-rustdoc.rs | 6 + src/test/ui/cfg-rustdoc.stderr | 9 + src/test/ui/chalkify/type_inference.stderr | 5 +- .../check-static-immutable-mut-slices.stderr | 7 +- .../expect-fn-supply-fn.nll.stderr | 1 + .../expect-fn-supply-fn.stderr | 11 +- .../expect-infer-var-appearing-twice.stderr | 1 + .../ui/closure-expected-type/issue-24421.rs | 2 +- .../closure-array-break-length.stderr | 8 +- .../expect-region-supply-region.nll.stderr | 2 + ...xpect-region-supply-region.polonius.stderr | 56 + .../expect-region-supply-region.stderr | 8 +- .../closure-immutable-outer-variable.stderr | 1 + src/test/ui/closures/closure-move-sync.rs | 3 +- src/test/ui/closures/closure-move-sync.stderr | 8 +- src/test/ui/closures/closure-no-fn-1.stderr | 8 +- src/test/ui/closures/closure-no-fn-2.stderr | 8 +- .../ui/closures/closure-reform-bad.stderr | 4 +- src/test/ui/closures/issue-41366.stderr | 3 +- src/test/ui/closures/issue-52437.rs | 1 + src/test/ui/closures/issue-52437.stderr | 14 +- src/test/ui/closures/issue-67123.rs | 5 + src/test/ui/closures/issue-67123.stderr | 15 + .../ui/codemap_tests/bad-format-args.stderr | 2 +- src/test/ui/codemap_tests/tab.stderr | 5 +- src/test/ui/codemap_tests/unicode_3.rs | 2 +- .../coerce-expect-unsized-ascribed.stderr | 84 +- .../coercion/coerce-issue-49593-box-never.rs | 3 +- src/test/ui/coercion/coerce-mut.rs | 4 +- src/test/ui/coercion/coerce-mut.stderr | 4 +- src/test/ui/coercion/coerce-to-bang.stderr | 26 +- ...coercion-missing-tail-expected-type.stderr | 11 +- src/test/ui/coercion/coercion-slice.rs | 3 +- src/test/ui/coercion/coercion-slice.stderr | 12 +- .../coherence/coherence-all-remote.re.stderr | 11 - src/test/ui/coherence/coherence-all-remote.rs | 6 +- ...old.stderr => coherence-all-remote.stderr} | 3 +- src/test/ui/coherence/coherence-bigint-int.rs | 3 - .../coherence-bigint-param.old.stderr | 11 - .../coherence-bigint-param.re.stderr | 11 - .../ui/coherence/coherence-bigint-param.rs | 6 +- .../coherence/coherence-bigint-param.stderr | 12 + .../ui/coherence/coherence-bigint-vecint.rs | 3 - ...nflicts-with-blanket-implemented.re.stderr | 12 - ...nket-conflicts-with-blanket-implemented.rs | 7 +- ...conflicts-with-blanket-implemented.stderr} | 2 +- ...icts-with-blanket-unimplemented.old.stderr | 12 - ...et-conflicts-with-blanket-unimplemented.rs | 7 +- ...nflicts-with-blanket-unimplemented.stderr} | 2 +- ...flicts-with-specific-cross-crate.re.stderr | 13 - ...ket-conflicts-with-specific-cross-crate.rs | 6 +- ...onflicts-with-specific-cross-crate.stderr} | 2 +- ...icts-with-specific-multidispatch.re.stderr | 12 - ...t-conflicts-with-specific-multidispatch.rs | 7 +- ...flicts-with-specific-multidispatch.stderr} | 2 +- ...et-conflicts-with-specific-trait.re.stderr | 12 - ...e-blanket-conflicts-with-specific-trait.rs | 7 +- ...nket-conflicts-with-specific-trait.stderr} | 2 +- ...-blanket-conflicts-with-specific.re.stderr | 12 - ...herence-blanket-conflicts-with-specific.rs | 7 +- ...ce-blanket-conflicts-with-specific.stderr} | 2 +- src/test/ui/coherence/coherence-blanket.rs | 3 - ...-conflicting-negative-trait-impl.re.stderr | 21 - ...herence-conflicting-negative-trait-impl.rs | 9 +- ...ce-conflicting-negative-trait-impl.stderr} | 4 +- .../coherence-covered-type-parameter.rs | 3 - src/test/ui/coherence/coherence-cow.a.stderr | 11 - src/test/ui/coherence/coherence-cow.b.stderr | 11 - src/test/ui/coherence/coherence-cow.c.stderr | 11 - .../ui/coherence/coherence-cow.re_b.stderr | 2 +- .../ui/coherence/coherence-cow.re_c.stderr | 2 +- src/test/ui/coherence/coherence-cow.rs | 19 +- .../coherence-cross-crate-conflict.re.stderr | 21 - .../coherence-cross-crate-conflict.rs | 9 +- ... => coherence-cross-crate-conflict.stderr} | 5 +- .../coherence-default-trait-impl.re.stderr | 16 - .../coherence/coherence-default-trait-impl.rs | 9 +- ...rr => coherence-default-trait-impl.stderr} | 4 +- .../coherence-error-suppression.old.stderr | 9 - .../coherence/coherence-error-suppression.rs | 7 +- ...err => coherence-error-suppression.stderr} | 2 +- ...erence-fundamental-trait-objects.re.stderr | 14 - .../coherence-fundamental-trait-objects.rs | 6 +- ...oherence-fundamental-trait-objects.stderr} | 2 +- src/test/ui/coherence/coherence-impl-in-fn.rs | 3 - ...impl-trait-for-trait-object-safe.re.stderr | 11 - ...erence-impl-trait-for-trait-object-safe.rs | 7 +- ...e-impl-trait-for-trait-object-safe.stderr} | 2 +- .../coherence-impl-trait-for-trait.re.stderr | 21 - .../coherence-impl-trait-for-trait.rs | 13 +- ... => coherence-impl-trait-for-trait.stderr} | 6 +- .../coherence/coherence-impls-copy.re.stderr | 95 - src/test/ui/coherence/coherence-impls-copy.rs | 33 +- ...old.stderr => coherence-impls-copy.stderr} | 20 +- .../coherence/coherence-impls-send.old.stderr | 43 - src/test/ui/coherence/coherence-impls-send.rs | 15 +- ....re.stderr => coherence-impls-send.stderr} | 8 +- .../coherence/coherence-impls-sized.re.stderr | 73 - .../ui/coherence/coherence-impls-sized.rs | 36 +- ...ld.stderr => coherence-impls-sized.stderr} | 18 +- ...nce-inherited-assoc-ty-cycle-err.re.stderr | 16 - .../coherence-inherited-assoc-ty-cycle-err.rs | 7 +- ...rence-inherited-assoc-ty-cycle-err.stderr} | 4 +- .../coherence-iterator-vec-any-elem.rs | 3 - .../ui/coherence/coherence-iterator-vec.rs | 3 - .../coherence-lone-type-parameter.re.stderr | 11 - .../coherence-lone-type-parameter.rs | 6 +- ...r => coherence-lone-type-parameter.stderr} | 3 +- .../coherence-multidispatch-tuple.rs | 3 - .../coherence-negative-impls-safe-rpass.rs | 3 - .../coherence-negative-impls-safe.re.stderr | 9 - .../coherence-negative-impls-safe.rs | 6 +- ...r => coherence-negative-impls-safe.stderr} | 2 +- ...ence-no-direct-lifetime-dispatch.re.stderr | 11 - .../coherence-no-direct-lifetime-dispatch.rs | 7 +- ...erence-no-direct-lifetime-dispatch.stderr} | 2 +- .../ui/coherence/coherence-orphan.re.stderr | 26 - src/test/ui/coherence/coherence-orphan.rs | 9 +- ...han.old.stderr => coherence-orphan.stderr} | 4 +- ...oherence-overlap-all-t-and-tuple.re.stderr | 12 - .../coherence-overlap-all-t-and-tuple.rs | 7 +- ... coherence-overlap-all-t-and-tuple.stderr} | 2 +- ...ence-overlap-downstream-inherent.re.stderr | 23 - .../coherence-overlap-downstream-inherent.rs | 10 +- ...erence-overlap-downstream-inherent.stderr} | 8 +- .../coherence-overlap-downstream.re.stderr | 21 - .../coherence/coherence-overlap-downstream.rs | 10 +- ...rr => coherence-overlap-downstream.stderr} | 4 +- ...nce-overlap-issue-23516-inherent.re.stderr | 14 - .../coherence-overlap-issue-23516-inherent.rs | 7 +- ...rence-overlap-issue-23516-inherent.stderr} | 4 +- .../coherence-overlap-issue-23516.re.stderr | 13 - .../coherence-overlap-issue-23516.rs | 7 +- ...r => coherence-overlap-issue-23516.stderr} | 2 +- .../coherence-overlap-messages.re.stderr | 44 - .../coherence/coherence-overlap-messages.rs | 19 +- ...derr => coherence-overlap-messages.stderr} | 10 +- ...erence-overlap-upstream-inherent.re.stderr | 14 - .../coherence-overlap-upstream-inherent.rs | 6 +- ...oherence-overlap-upstream-inherent.stderr} | 4 +- .../coherence-overlap-upstream.re.stderr | 13 - .../coherence/coherence-overlap-upstream.rs | 6 +- ...derr => coherence-overlap-upstream.stderr} | 2 +- .../coherence-overlapping-pairs.old.stderr | 11 - .../coherence/coherence-overlapping-pairs.rs | 6 +- ...err => coherence-overlapping-pairs.stderr} | 2 +- ...erence-pair-covered-uncovered-1.old.stderr | 11 - .../coherence-pair-covered-uncovered-1.rs | 6 +- ...coherence-pair-covered-uncovered-1.stderr} | 2 +- ...oherence-pair-covered-uncovered.old.stderr | 11 - .../coherence-pair-covered-uncovered.rs | 6 +- ...> coherence-pair-covered-uncovered.stderr} | 2 +- ...rence-projection-conflict-orphan.re.stderr | 14 - .../coherence-projection-conflict-orphan.rs | 6 +- ...herence-projection-conflict-orphan.stderr} | 2 +- ...nce-projection-conflict-ty-param.re.stderr | 12 - .../coherence-projection-conflict-ty-param.rs | 7 +- ...rence-projection-conflict-ty-param.stderr} | 2 +- .../coherence-projection-conflict.re.stderr | 12 - .../coherence-projection-conflict.rs | 7 +- ...r => coherence-projection-conflict.stderr} | 2 +- .../coherence-projection-ok-orphan.rs | 3 - .../ui/coherence/coherence-projection-ok.rs | 3 - .../coherence/coherence-rfc447-constrained.rs | 3 - src/test/ui/coherence/coherence-subtyping.rs | 2 - .../coherence-tuple-conflict.re.stderr | 12 - .../ui/coherence/coherence-tuple-conflict.rs | 7 +- ...stderr => coherence-tuple-conflict.stderr} | 2 +- .../coherence-vec-local-2.old.stderr | 11 - .../ui/coherence/coherence-vec-local-2.rs | 6 +- ...re.stderr => coherence-vec-local-2.stderr} | 2 +- .../coherence/coherence-vec-local.old.stderr | 14 - src/test/ui/coherence/coherence-vec-local.rs | 6 +- ...l.re.stderr => coherence-vec-local.stderr} | 2 +- .../ui/coherence/coherence-where-clause.rs | 3 - src/test/ui/coherence/coherence_copy_like.rs | 3 - ...erence_copy_like_err_fundamental_struct.rs | 3 - ...ce_copy_like_err_fundamental_struct_ref.rs | 3 - ...ike_err_fundamental_struct_tuple.re.stderr | 14 - ..._copy_like_err_fundamental_struct_tuple.rs | 6 +- ..._like_err_fundamental_struct_tuple.stderr} | 2 +- .../coherence_copy_like_err_struct.re.stderr | 14 - .../coherence_copy_like_err_struct.rs | 6 +- ... => coherence_copy_like_err_struct.stderr} | 2 +- .../coherence_copy_like_err_tuple.re.stderr | 14 - .../coherence_copy_like_err_tuple.rs | 6 +- ...r => coherence_copy_like_err_tuple.stderr} | 2 +- .../ui/coherence/coherence_inherent.re.stderr | 13 - src/test/ui/coherence/coherence_inherent.rs | 7 +- ...t.old.stderr => coherence_inherent.stderr} | 2 +- .../coherence/coherence_inherent_cc.re.stderr | 13 - .../ui/coherence/coherence_inherent_cc.rs | 6 +- ...ld.stderr => coherence_inherent_cc.stderr} | 2 +- src/test/ui/coherence/coherence_local.rs | 3 - .../coherence_local_err_struct.re.stderr | 14 - .../coherence/coherence_local_err_struct.rs | 6 +- ...derr => coherence_local_err_struct.stderr} | 2 +- .../coherence_local_err_tuple.old.stderr | 14 - .../ui/coherence/coherence_local_err_tuple.rs | 6 +- ...tderr => coherence_local_err_tuple.stderr} | 2 +- src/test/ui/coherence/coherence_local_ref.rs | 3 - .../ui/coherence/impl-foreign-for-foreign.rs | 2 - .../coherence/impl-foreign-for-foreign.stderr | 2 +- .../impl-foreign-for-foreign[foreign].rs | 2 - .../impl-foreign-for-foreign[foreign].stderr | 6 +- .../impl-foreign-for-foreign[local].rs | 2 - .../impl-foreign-for-fundamental[foreign].rs | 2 - ...pl-foreign-for-fundamental[foreign].stderr | 4 +- .../impl-foreign-for-fundamental[local].rs | 2 - .../ui/coherence/impl-foreign-for-local.rs | 2 - ...foreign-for-locally-defined-fundamental.rs | 1 - ...or-locally-defined-fundamental[foreign].rs | 1 - .../impl-foreign[foreign]-for-foreign.rs | 2 - .../impl-foreign[foreign]-for-foreign.stderr | 2 +- .../impl-foreign[foreign]-for-local.rs | 2 - ...reign[fundemental[foreign]]-for-foreign.rs | 2 - ...n[fundemental[foreign]]-for-foreign.stderr | 6 +- ...foreign[fundemental[local]]-for-foreign.rs | 2 - .../impl[t]-foreign-for-foreign[t].rs | 2 - .../impl[t]-foreign-for-foreign[t].stderr | 4 +- .../impl[t]-foreign-for-fundamental[t].rs | 2 - .../impl[t]-foreign-for-fundamental[t].stderr | 3 +- ...]-foreign[foreign[t]_local]-for-foreign.rs | 2 - ...[t]-foreign[foreign]-for-fundamental[t].rs | 2 - ...foreign[foreign]-for-fundamental[t].stderr | 6 +- .../impl[t]-foreign[foreign]-for-t.rs | 2 - .../impl[t]-foreign[foreign]-for-t.stderr | 3 +- ...[t]-foreign[fundamental[t]]-for-foreign.rs | 2 - ...foreign[fundamental[t]]-for-foreign.stderr | 6 +- ...eign[fundamental[t]]-for-fundamental[t].rs | 2 - ...[fundamental[t]]-for-fundamental[t].stderr | 6 +- ...pl[t]-foreign[fundamental[t]]-for-local.rs | 2 - .../impl[t]-foreign[fundamental[t]]-for-t.rs | 2 - ...pl[t]-foreign[fundamental[t]]-for-t.stderr | 6 +- ...reign[fundamental[t]_local]-for-foreign.rs | 6 +- ...n[fundamental[t]_local]-for-foreign.stderr | 18 +- ...eign[fundemental[local]]-for-foreign[t].rs | 2 - .../impl[t]-foreign[local]-for-foreign.rs | 2 - .../impl[t]-foreign[local]-for-foreign[t].rs | 2 - ...eign[local]-for-fundamental[foreign[t]].rs | 2 - ...pl[t]-foreign[local]-for-fundamental[t].rs | 6 +- ...]-foreign[local]-for-fundamental[t].stderr | 18 +- .../impl[t]-foreign[local]-for-local.rs | 2 - .../coherence/impl[t]-foreign[local]-for-t.rs | 4 +- .../impl[t]-foreign[local]-for-t.stderr | 9 +- ...reign[local_fundamental[t]]-for-foreign.rs | 2 - .../impl[t]-foreign[t]-for-foreign.rs | 2 - .../impl[t]-foreign[t]-for-foreign.stderr | 3 +- .../impl[t]-foreign[t]-for-fundamental.rs | 2 - .../impl[t]-foreign[t]-for-fundamental.stderr | 6 +- .../coherence/impl[t]-foreign[t]-for-local.rs | 2 - .../ui/coherence/impl[t]-foreign[t]-for-t.rs | 2 - .../coherence/impl[t]-foreign[t]-for-t.stderr | 3 +- ...herence-default-generic-associated-type.rs | 1 - .../ui/coherence/re-rebalance-coherence.rs | 2 - src/test/ui/command/command-argv0-debug.rs | 24 + src/test/ui/command/command-argv0.rs | 33 + src/test/ui/{ => command}/command-exec.rs | 0 src/test/ui/{ => command}/command-pre-exec.rs | 0 src/test/ui/{ => command}/command-uid-gid.rs | 0 .../reordered-type-param.stderr | 9 +- .../conditional-compilation/cfg-attr-parse.rs | 16 +- .../cfg-attr-parse.stderr | 64 +- .../cannot-infer-const-args.stderr | 2 +- ...const-argument-cross-crate-mismatch.stderr | 6 - .../const-expression-parameter.stderr | 2 +- .../const-generic-array-wrapper.rs | 6 +- .../ui/const-generics/fn-const-param-call.rs | 4 +- .../ui/const-generics/fn-const-param-infer.rs | 10 +- .../fn-const-param-infer.stderr | 32 +- .../impl-const-generic-struct.rs | 2 +- .../raw-ptr-const-param-deref.rs | 2 +- .../const-generics/raw-ptr-const-param.stderr | 8 +- .../slice-const-param-mismatch.stderr | 24 +- .../types-mismatch-const-args.stderr | 16 +- .../uninferred-consts-during-codegen-1.rs | 2 +- .../ui/consts/array-literal-index-oob.stderr | 2 +- .../auxiliary/promotable_const_fn_lib.rs | 2 + .../ui/consts/const-array-oob-arith.stderr | 6 - .../ui/consts/const-cast-wrong-type.stderr | 2 +- src/test/ui/consts/const-err2.rs | 1 - src/test/ui/consts/const-err2.stderr | 8 +- src/test/ui/consts/const-err3.rs | 1 - src/test/ui/consts/const-err3.stderr | 8 +- .../assign-to-static-within-other-static.rs | 3 +- ...ssign-to-static-within-other-static.stderr | 5 +- .../consts/const-eval/auxiliary/stability.rs | 4 +- .../const-eval-intrinsic-promotion.rs | 6 + .../const-eval-intrinsic-promotion.stderr | 13 + .../const-eval/const-eval-overflow-3b.stderr | 2 +- .../const-eval/const-eval-overflow-4b.rs | 2 +- .../const-eval/const-eval-overflow-4b.stderr | 2 +- .../ui/consts/const-eval/const-eval-span.rs | 3 +- .../consts/const-eval/const-eval-span.stderr | 5 +- .../const-eval/const_caller_location.rs | 23 - src/test/ui/consts/const-eval/const_fn_ptr.rs | 8 +- .../ui/consts/const-eval/const_fn_ptr.stderr | 10 +- .../dont_promote_unstable_const_fn.rs | 4 +- .../index-out-of-bounds-never-type.rs | 19 + .../index-out-of-bounds-never-type.stderr | 22 + .../ui/consts/const-eval/infinite_loop.rs | 4 +- .../ui/consts/const-eval/infinite_loop.stderr | 29 +- src/test/ui/consts/const-eval/issue-52442.rs | 1 + .../ui/consts/const-eval/issue-52442.stderr | 11 +- src/test/ui/consts/const-eval/issue-52475.rs | 3 +- .../ui/consts/const-eval/issue-52475.stderr | 21 +- src/test/ui/consts/const-eval/issue-62272.rs | 12 +- .../ui/consts/const-eval/issue-62272.stderr | 21 + src/test/ui/consts/const-eval/issue-64970.rs | 2 +- .../ui/consts/const-eval/issue-64970.stderr | 8 - src/test/ui/consts/const-eval/issue-65394.rs | 7 +- .../ui/consts/const-eval/issue-65394.stderr | 20 +- .../consts/const-eval/match-test-ptr-null.rs | 4 +- .../const-eval/match-test-ptr-null.stderr | 33 +- .../const-eval/panic-assoc-never-type.rs | 16 + .../const-eval/panic-assoc-never-type.stderr | 24 + .../ui/consts/const-eval/panic-never-type.rs | 12 + .../consts/const-eval/panic-never-type.stderr | 24 + .../ui/consts/const-eval/promote-static.rs | 14 + .../ui/consts/const-eval/promoted_errors.rs | 6 +- .../consts/const-eval/promoted_errors.stderr | 24 +- .../ui/consts/const-eval/promoted_errors2.rs | 6 +- .../consts/const-eval/promoted_errors2.stderr | 24 +- .../ui/consts/const-eval/ub-wide-ptr.stderr | 4 +- .../const-eval/validate_uninhabited_zsts.rs | 24 + .../validate_uninhabited_zsts.stderr | 54 + .../const-extern-fn-call-extern-fn.rs | 4 +- .../const-extern-fn-call-extern-fn.stderr | 4 +- ...nst-extern-fns-dont-need-fn-specifier-2.rs | 7 + ...extern-fns-dont-need-fn-specifier-2.stderr | 8 + ...const-extern-fns-dont-need-fn-specifier.rs | 8 + ...t-extern-fns-dont-need-fn-specifier.stderr | 18 + .../consts/const-fn-not-safe-for-const.stderr | 4 +- src/test/ui/consts/const-fn-zst-args.rs | 14 + src/test/ui/consts/const-if.rs | 5 - src/test/ui/consts/const-if.stderr | 15 - src/test/ui/consts/const-integer-bool-ops.rs | 36 +- .../ui/consts/const-integer-bool-ops.stderr | 60 +- src/test/ui/consts/const-labeled-break.rs | 8 +- src/test/ui/consts/const-labeled-break.stderr | 13 + src/test/ui/consts/const-match-pattern-arm.rs | 8 +- .../ui/consts/const-match-pattern-arm.stderr | 41 +- src/test/ui/consts/const-multi-ref.rs | 19 +- src/test/ui/consts/const-multi-ref.stderr | 18 +- .../consts/const-mut-refs/const_mut_refs.rs | 37 + .../feature-gate-const_mut_refs.rs | 7 + .../feature-gate-const_mut_refs.stderr | 12 + src/test/ui/consts/const-prop-ice.rs | 1 - src/test/ui/consts/const-prop-ice.stderr | 8 +- src/test/ui/consts/const-size_of-cycle.rs | 3 +- src/test/ui/consts/const-size_of-cycle.stderr | 11 +- src/test/ui/consts/const-tup-index-span.rs | 2 +- .../ui/consts/const-tup-index-span.stderr | 6 +- src/test/ui/consts/const-type-mismatch.stderr | 4 +- src/test/ui/consts/const_let_assign3.stderr | 14 +- src/test/ui/consts/const_let_promote.rs | 17 + src/test/ui/consts/const_let_refutable.stderr | 4 +- .../ui/consts/control-flow/assert.both.stderr | 13 + .../control-flow/assert.if_match.stderr | 23 + .../consts/control-flow/assert.panic.stderr | 21 + src/test/ui/consts/control-flow/assert.rs | 17 + .../consts/control-flow/assert.stock.stderr | 21 + src/test/ui/consts/control-flow/basics.rs | 87 + .../ui/consts/control-flow/drop-failure.rs | 61 + .../consts/control-flow/drop-failure.stderr | 27 + .../ui/consts/control-flow/drop-success.rs | 45 + .../exhaustive-c-like-enum-match.rs | 32 + ...eature-gate-const-if-match.if_match.stderr | 14 + .../feature-gate-const-if-match.rs | 119 + .../feature-gate-const-if-match.stock.stderr | 249 + .../control-flow/interior-mutability.rs | 47 + .../control-flow/interior-mutability.stderr | 35 + .../control-flow/issue-46843.if_match.stderr | 9 + .../ui/consts/control-flow/issue-46843.rs | 18 + .../control-flow/issue-46843.stock.stderr | 18 + .../control-flow/issue-50577.if_match.stderr} | 6 +- .../ui/consts/control-flow/issue-50577.rs | 13 + .../control-flow/issue-50577.stock.stderr | 47 + .../ui/consts/control-flow/loop.both.stderr | 19 + .../consts/control-flow/loop.if_match.stderr | 151 + .../ui/consts/control-flow/loop.loop_.stderr | 96 + src/test/ui/consts/control-flow/loop.rs | 99 + .../ui/consts/control-flow/loop.stock.stderr | 178 + .../consts/control-flow/short-circuit-let.rs | 40 + .../short-circuit.if_match.stderr | 8 + .../ui/consts/control-flow/short-circuit.rs | 14 + .../control-flow/short-circuit.stock.stderr | 23 + .../control-flow/single_variant_match_ice.rs | 27 + src/test/ui/consts/control-flow/try.rs | 12 + src/test/ui/consts/control-flow/try.stderr | 9 + src/test/ui/consts/enum-discr-type-err.stderr | 2 +- src/test/ui/consts/huge-values.rs | 11 + src/test/ui/consts/issue-52432.rs | 10 + src/test/ui/consts/issue-52432.stderr | 28 + src/test/ui/consts/issue-62045.rs | 2 +- src/test/ui/consts/issue-64662.stderr | 4 +- src/test/ui/consts/issue-66345.rs | 24 + src/test/ui/consts/issue-66787.rs | 39 + .../consts/min_const_fn/allow_const_fn_ptr.rs | 2 + .../min_const_fn/allow_const_fn_ptr.stderr | 2 +- .../allow_const_fn_ptr_run_pass.rs | 1 + src/test/ui/consts/min_const_fn/loop_ice.rs | 2 +- .../ui/consts/min_const_fn/loop_ice.stderr | 8 +- .../ui/consts/min_const_fn/min_const_fn.rs | 5 - .../consts/min_const_fn/min_const_fn.stderr | 65 +- .../consts/min_const_fn/min_const_fn_dyn.rs | 1 - .../min_const_fn/min_const_fn_dyn.stderr | 14 +- .../min_const_fn_libstd_stability.rs | 8 +- .../min_const_fn_libstd_stability.stderr | 8 +- .../min_const_unsafe_fn_libstd_stability.rs | 8 +- ...in_const_unsafe_fn_libstd_stability.stderr | 8 +- .../min_const_unsafe_fn_libstd_stability2.rs | 7 +- ...n_const_unsafe_fn_libstd_stability2.stderr | 6 +- .../miri_unleashed/enum_discriminants.stderr | 24 - .../ui/consts/miri_unleashed/mutable_const.rs | 5 +- .../miri_unleashed/mutable_const.stderr | 13 +- .../miri_unleashed/mutable_references.rs | 10 +- .../miri_unleashed/mutable_references.stderr | 29 +- .../consts/miri_unleashed/read_from_static.rs | 11 + src/test/ui/consts/offset_from.rs | 6 + src/test/ui/consts/offset_from_ub.rs | 18 +- src/test/ui/consts/offset_from_ub.stderr | 47 +- src/test/ui/consts/packed_pattern.rs | 2 +- src/test/ui/consts/packed_pattern2.rs | 2 +- .../consts/projection_qualif.mut_refs.stderr | 12 + src/test/ui/consts/projection_qualif.rs | 8 +- ....stderr => projection_qualif.stock.stderr} | 23 +- src/test/ui/consts/promote_borrowed_field.rs | 12 + .../const-fns.rs | 26 - .../fn-call-in-const.rs | 23 + .../fn-call-in-non-const.rs | 18 + ...fns.stderr => fn-call-in-non-const.stderr} | 6 +- .../ui/consts/single_variant_match_ice.rs | 24 - .../ui/consts/single_variant_match_ice.stderr | 25 - ...ic_mut_containing_mut_ref2.mut_refs.stderr | 9 + .../consts/static_mut_containing_mut_ref2.rs | 9 +- ...atic_mut_containing_mut_ref2.stock.stderr} | 13 +- .../consts/uninhabited-const-issue-61744.rs | 6 +- .../uninhabited-const-issue-61744.stderr | 80 +- .../ui/consts/unstable-const-fn-in-libcore.rs | 29 + .../unstable-const-fn-in-libcore.stderr | 22 + .../ui/continue-after-missing-main.stderr | 3 +- src/test/ui/conversion-methods.stderr | 51 +- src/test/ui/cross/cross-borrow-trait.rs | 4 +- src/test/ui/cross/cross-borrow-trait.stderr | 13 +- .../ui/deprecation/deprecation-in-future.rs | 1 + src/test/ui/deref-suggestion.stderr | 49 +- .../derives-span-Clone-enum-struct-variant.rs | 1 + ...ives-span-Clone-enum-struct-variant.stderr | 2 +- .../ui/derives/derives-span-Clone-enum.rs | 1 + .../ui/derives/derives-span-Clone-enum.stderr | 2 +- .../ui/derives/derives-span-Clone-struct.rs | 1 + .../derives/derives-span-Clone-struct.stderr | 2 +- .../derives-span-Clone-tuple-struct.rs | 1 + .../derives-span-Clone-tuple-struct.stderr | 2 +- .../derives-span-Debug-enum-struct-variant.rs | 1 + ...ives-span-Debug-enum-struct-variant.stderr | 2 +- .../ui/derives/derives-span-Debug-enum.rs | 1 + .../ui/derives/derives-span-Debug-enum.stderr | 2 +- .../ui/derives/derives-span-Debug-struct.rs | 1 + .../derives/derives-span-Debug-struct.stderr | 2 +- .../derives-span-Debug-tuple-struct.rs | 1 + .../derives-span-Debug-tuple-struct.stderr | 2 +- .../ui/derives/derives-span-Default-struct.rs | 1 + .../derives-span-Default-struct.stderr | 2 +- .../derives-span-Default-tuple-struct.rs | 1 + .../derives-span-Default-tuple-struct.stderr | 2 +- .../derives-span-Eq-enum-struct-variant.rs | 1 + ...derives-span-Eq-enum-struct-variant.stderr | 2 +- src/test/ui/derives/derives-span-Eq-enum.rs | 1 + .../ui/derives/derives-span-Eq-enum.stderr | 2 +- src/test/ui/derives/derives-span-Eq-struct.rs | 1 + .../ui/derives/derives-span-Eq-struct.stderr | 2 +- .../derives/derives-span-Eq-tuple-struct.rs | 1 + .../derives-span-Eq-tuple-struct.stderr | 2 +- .../derives-span-Hash-enum-struct-variant.rs | 3 +- ...rives-span-Hash-enum-struct-variant.stderr | 2 +- src/test/ui/derives/derives-span-Hash-enum.rs | 3 +- .../ui/derives/derives-span-Hash-enum.stderr | 2 +- .../ui/derives/derives-span-Hash-struct.rs | 3 +- .../derives/derives-span-Hash-struct.stderr | 2 +- .../derives/derives-span-Hash-tuple-struct.rs | 3 +- .../derives-span-Hash-tuple-struct.stderr | 2 +- .../derives-span-Ord-enum-struct-variant.rs | 1 + ...erives-span-Ord-enum-struct-variant.stderr | 2 +- src/test/ui/derives/derives-span-Ord-enum.rs | 1 + .../ui/derives/derives-span-Ord-enum.stderr | 2 +- .../ui/derives/derives-span-Ord-struct.rs | 1 + .../ui/derives/derives-span-Ord-struct.stderr | 2 +- .../derives/derives-span-Ord-tuple-struct.rs | 1 + .../derives-span-Ord-tuple-struct.stderr | 2 +- ...ives-span-PartialEq-enum-struct-variant.rs | 1 + ...-span-PartialEq-enum-struct-variant.stderr | 4 +- .../ui/derives/derives-span-PartialEq-enum.rs | 1 + .../derives-span-PartialEq-enum.stderr | 4 +- .../derives/derives-span-PartialEq-struct.rs | 1 + .../derives-span-PartialEq-struct.stderr | 4 +- .../derives-span-PartialEq-tuple-struct.rs | 1 + ...derives-span-PartialEq-tuple-struct.stderr | 4 +- ...ves-span-PartialOrd-enum-struct-variant.rs | 1 + ...span-PartialOrd-enum-struct-variant.stderr | 2 +- .../derives/derives-span-PartialOrd-enum.rs | 1 + .../derives-span-PartialOrd-enum.stderr | 2 +- .../derives/derives-span-PartialOrd-struct.rs | 1 + .../derives-span-PartialOrd-struct.stderr | 2 +- .../derives-span-PartialOrd-tuple-struct.rs | 1 + ...erives-span-PartialOrd-tuple-struct.stderr | 2 +- src/test/ui/derives/deriving-copyclone.rs | 6 +- src/test/ui/derives/deriving-copyclone.stderr | 15 +- src/test/ui/destructure-trait-ref.rs | 16 +- src/test/ui/destructure-trait-ref.stderr | 18 +- src/test/ui/did_you_mean/issue-35937.stderr | 3 +- src/test/ui/did_you_mean/issue-39544.stderr | 3 +- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- src/test/ui/did_you_mean/issue-42764.stderr | 7 +- ...xpected-float-found-integer-literal.stderr | 50 +- ...sue-54109-and_instead_of_ampersands.stderr | 8 +- .../did_you_mean/recursion_limit_deref.stderr | 8 +- src/test/ui/discrim/discrim-ill-typed.rs | 16 +- src/test/ui/discrim/discrim-ill-typed.stderr | 16 +- src/test/ui/diverging-fn-tail-35849.stderr | 4 +- .../ui/diverging-tuple-parts-39485.stderr | 10 +- src/test/ui/drop/dynamic-drop.rs | 32 + src/test/ui/dst/dst-bad-assign-3.rs | 6 +- src/test/ui/dst/dst-bad-assign-3.stderr | 6 +- src/test/ui/dst/dst-bad-assign.rs | 6 +- src/test/ui/dst/dst-bad-assign.stderr | 6 +- src/test/ui/dst/dst-bad-coerce1.stderr | 16 +- src/test/ui/dst/dst-bad-coerce2.stderr | 32 +- src/test/ui/dst/dst-bad-coerce4.rs | 12 +- src/test/ui/dst/dst-bad-coerce4.stderr | 16 +- src/test/ui/dst/dst-bad-coercions.stderr | 66 +- .../issue-56327-dyn-trait-in-macro-is-okay.rs | 2 +- .../edition-keywords-2018-2015-parsing.stderr | 2 +- .../edition-keywords-2018-2018-parsing.stderr | 2 +- .../elide-errors-on-mismatched-tuple.stderr | 4 +- .../enum-discriminant/discriminant_value.rs | 45 +- .../niche.rs} | 4 +- src/test/ui/enum/nested-enum.rs | 8 + src/test/ui/enum/nested-enum.stderr | 26 + src/test/ui/enum/union-in-enum.rs | 13 + src/test/ui/error-codes/E0004-2.stderr | 4 +- src/test/ui/error-codes/E0017.rs | 10 +- src/test/ui/error-codes/E0017.stderr | 46 +- src/test/ui/error-codes/E0029-teach.stderr | 7 +- src/test/ui/error-codes/E0029.stderr | 8 +- src/test/ui/error-codes/E0070.stderr | 5 +- src/test/ui/error-codes/E0161.rs | 10 +- src/test/ui/error-codes/E0271.stderr | 5 +- src/test/ui/error-codes/E0283.stderr | 6 +- src/test/ui/error-codes/E0308-4.stderr | 2 +- src/test/ui/error-codes/E0308.stderr | 6 +- src/test/ui/error-codes/E0388.rs | 8 +- src/test/ui/error-codes/E0388.stderr | 25 +- src/test/ui/error-codes/E0389.stderr | 1 + src/test/ui/error-codes/E0401.stderr | 2 +- src/test/ui/error-codes/E0511.stderr | 1 + src/test/ui/error-codes/E0594.stderr | 1 + src/test/ui/error-codes/E0660.stderr | 1 + src/test/ui/error-codes/E0661.stderr | 3 +- src/test/ui/error-codes/E0662.stderr | 1 + src/test/ui/error-codes/E0663.stderr | 1 + src/test/ui/error-codes/E0664.stderr | 1 + src/test/ui/error-codes/E0665.stderr | 1 + src/test/ui/error-codes/e0119/complex-impl.rs | 2 +- .../ui/error-codes/e0119/complex-impl.stderr | 15 +- .../ui/error-codes/e0119/issue-28981.stderr | 1 + src/test/ui/estr-subtyping.stderr | 5 +- ...sive_range_pattern_syntax_collision.stderr | 4 +- ...ive_range_pattern_syntax_collision2.stderr | 4 +- ...ive_range_pattern_syntax_collision3.stderr | 8 +- .../explicit-self-lifetime-mismatch.rs | 8 +- .../explicit-self-lifetime-mismatch.stderr | 8 +- src/test/ui/extern-flag/auxiliary/somedep.rs | 3 + src/test/ui/extern-flag/multiple-opts.rs | 20 + src/test/ui/extern-flag/multiple-opts.stderr | 9 + .../ui/extern-flag/noprelude-and-prelude.rs | 10 + src/test/ui/extern-flag/noprelude-resolves.rs | 11 + src/test/ui/extern-flag/noprelude.rs | 7 + src/test/ui/extern-flag/noprelude.stderr | 9 + src/test/ui/extern-flag/public-and-private.rs | 13 + .../ui/extern-flag/public-and-private.stderr | 14 + src/test/ui/extern/extern-main-fn.stderr | 4 +- src/test/ui/extern/extern-prelude-core.rs | 2 +- src/test/ui/extern/extern-prelude-core.stderr | 8 - src/test/ui/extern/extern-prelude-std.rs | 1 - src/test/ui/extern/extern-prelude-std.stderr | 8 - .../extern/extern-types-distinct-types.stderr | 4 +- .../issue-36122-accessing-externed-dst.rs | 6 + .../issue-36122-accessing-externed-dst.stderr | 12 + .../ui/feature-gate/allow-features-empty.rs | 2 - .../feature-gate/allow-features-empty.stderr | 12 +- src/test/ui/feature-gate/allow-features.rs | 2 - .../ui/feature-gate/allow-features.stderr | 10 +- .../issue-43106-gating-of-inline.rs | 2 +- .../issue-43106-gating-of-inline.stderr | 6 +- .../issue-43106-gating-of-macro_escape.rs | 2 +- .../unstable-attribute-allow-issue-none.rs | 13 + ...unstable-attribute-allow-issue-none.stderr | 8 + .../feature-gated-feature-in-macro-arg.stderr | 8 +- .../feature-gate-abi-msp430-interrupt.stderr | 4 +- .../ui/feature-gates/feature-gate-abi.stderr | 272 +- .../feature-gate-abi_unadjusted.stderr | 8 +- .../feature-gate-cfg_sanitize.rs | 3 + .../feature-gate-cfg_sanitize.stderr | 12 + ...e-const_in_array_repeat_expressions.stderr | 2 +- .../feature-gate-const_transmute.rs | 2 +- .../feature-gate-const_transmute.stderr | 4 +- .../feature-gate-custom_attribute2.rs | 2 - .../feature-gate-custom_attribute2.stderr | 34 +- .../feature-gate-doc_cfg-cfg-rustdoc.rs | 4 - .../feature-gate-doc_cfg-cfg-rustdoc.stderr | 12 - .../feature-gate-extern_prelude.stderr | 2 +- .../feature-gate-intrinsics.stderr | 12 +- .../feature-gate-on-unimplemented.rs | 9 - .../feature-gate-re-rebalance-coherence.rs | 13 - ...feature-gate-re-rebalance-coherence.stderr | 11 - .../feature-gate-register_attr.rs | 3 + .../feature-gate-register_attr.stderr | 12 + .../feature-gate-register_tool.rs | 3 + .../feature-gate-register_tool.stderr | 12 + .../feature-gate-rustc_const_unstable.rs | 5 +- .../feature-gate-rustc_const_unstable.stderr | 8 +- .../feature-gate-type_alias_impl_trait.rs | 36 +- .../feature-gate-type_alias_impl_trait.stderr | 149 +- ...-gate-unboxed-closures-manual-impls.stderr | 16 +- .../feature-gate-unboxed-closures.stderr | 8 +- ...loat-literal-inference-restrictions.stderr | 16 +- src/test/ui/fmt/format-string-error.rs | 6 +- src/test/ui/fmt/format-string-error.stderr | 44 +- src/test/ui/fn/fn-bad-block-type.stderr | 2 +- .../ui/fn/fn-closure-mutable-capture.stderr | 1 + src/test/ui/fn/fn-compare-mismatch.stderr | 4 +- src/test/ui/fn/fn-item-type.rs | 12 +- src/test/ui/fn/fn-item-type.stderr | 20 +- src/test/ui/fn/fn-trait-formatting.rs | 12 +- src/test/ui/fn/fn-trait-formatting.stderr | 24 +- .../ui/for-loop-while/label_break_value.rs | 2 +- .../ui/for-loop-while/loop-label-shadowing.rs | 1 + .../fully-qualified-type-name1.rs | 2 +- .../fully-qualified-type-name1.stderr | 2 +- .../fully-qualified-type-name2.rs | 2 - .../fully-qualified-type-name2.stderr | 3 - .../fully-qualified-type-name4.rs | 4 +- .../fully-qualified-type-name4.stderr | 7 +- .../generator/async-generator-issue-67158.rs | 6 + .../async-generator-issue-67158.stderr | 8 + src/test/ui/generator/issue-53548-1.rs | 2 +- src/test/ui/generator/issue-53548.rs | 2 +- src/test/ui/generator/not-send-sync.rs | 2 +- src/test/ui/generator/not-send-sync.stderr | 15 +- .../static-mut-reference-across-yield.rs | 29 + .../static-reference-across-yield.rs | 16 + .../type-mismatch-signature-deduction.stderr | 4 +- .../generic-arg-mismatch-recover.stderr | 6 +- .../generic/generic-type-params-name-repr.rs | 36 +- .../generic-type-params-name-repr.stderr | 48 +- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 4 +- .../hr-subtype.bound_a_b_vs_bound_a.stderr | 4 +- .../hr-subtype.bound_a_vs_bound_a.stderr | 2 +- .../hr-subtype.bound_a_vs_bound_b.stderr | 2 +- .../hr-subtype.bound_a_vs_free_x.stderr | 4 +- ...-subtype.bound_co_a_b_vs_bound_co_a.stderr | 4 +- ...ubtype.bound_co_a_co_b_ret_contra_a.stderr | 4 +- ...hr-subtype.bound_co_a_vs_bound_co_b.stderr | 2 +- ...pe.bound_contra_a_contra_b_ret_co_a.stderr | 4 +- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 4 +- ...-subtype.bound_inv_a_vs_bound_inv_b.stderr | 2 +- ...ubtype.free_inv_x_vs_free_inv_y.nll.stderr | 4 + ...hr-subtype.free_inv_x_vs_free_inv_y.stderr | 8 +- .../hr-subtype.free_x_vs_free_x.stderr | 2 +- .../hr-subtype.free_x_vs_free_y.nll.stderr | 2 + .../hr-subtype.free_x_vs_free_y.stderr | 4 +- src/test/ui/hr-subtype/hr-subtype.rs | 10 +- src/test/ui/hrtb/hrtb-exists-forall-fn.stderr | 8 +- ...igher-ranker-supertraits-transitive.stderr | 2 +- .../hrtb-higher-ranker-supertraits.stderr | 4 +- .../hrtb/hrtb-perfect-forwarding.nll.stderr | 2 + .../hrtb-perfect-forwarding.polonius.stderr | 68 + src/test/ui/hrtb/issue-62203-hrtb-ice.stderr | 6 +- src/test/ui/hygiene/dollar-crate-modern.rs | 2 +- .../ui/hygiene/dollar-crate-modern.stderr | 8 - src/test/ui/hygiene/generic_params.rs | 1 + src/test/ui/hygiene/hygienic-labels-in-let.rs | 29 + .../ui/hygiene/hygienic-labels-in-let.stderr | 62 +- src/test/ui/hygiene/hygienic-labels.rs | 32 + src/test/ui/hygiene/hygienic-labels.stderr | 61 +- .../hygiene/issue-61574-const-parameters.rs | 2 +- src/test/ui/if-else-type-mismatch.stderr | 40 +- src/test/ui/if-ret.rs | 2 +- src/test/ui/if/if-branch-types.rs | 2 +- src/test/ui/if/if-branch-types.stderr | 5 +- src/test/ui/if/if-let-arm-types.rs | 3 +- src/test/ui/if/if-let-arm-types.stderr | 5 +- src/test/ui/if/if-no-match-bindings.stderr | 40 +- src/test/ui/if/if-typeck.stderr | 4 +- .../ui/if/if-without-else-as-fn-expr.stderr | 24 +- src/test/ui/if/if-without-else-result.rs | 4 +- src/test/ui/if/if-without-else-result.stderr | 4 +- src/test/ui/if/ifmt-bad-arg.stderr | 26 +- src/test/ui/if/ifmt-unknown-trait.stderr | 4 +- src/test/ui/ifmt.rs | 2 + src/test/ui/immut-function-arguments.stderr | 1 + .../dyn-trait.nll.stderr | 2 + .../dyn-trait.stderr | 20 +- .../bound-normalization-fail.stderr | 12 +- src/test/ui/impl-trait/equality.rs | 2 +- src/test/ui/impl-trait/equality.stderr | 5 +- src/test/ui/impl-trait/equality2.rs | 12 +- src/test/ui/impl-trait/equality2.stderr | 28 +- .../impl-generic-mismatch-ab.stderr | 8 +- .../ui/impl-trait/impl-generic-mismatch.rs | 3 +- .../impl-trait/impl-generic-mismatch.stderr | 6 +- src/test/ui/impl-trait/issues/issue-42479.rs | 2 +- src/test/ui/impl-trait/issues/issue-49376.rs | 2 +- src/test/ui/impl-trait/issues/issue-52128.rs | 2 +- .../issue-55608-captures-empty-region.rs | 2 +- .../issues/issue-57464-unexpected-regions.rs | 2 +- ...-deeply-nested-impl-trait-in-assoc-proj.rs | 37 +- ...ply-nested-impl-trait-in-assoc-proj.stderr | 32 +- .../issues/issue-57979-impl-trait-in-path.rs | 35 +- .../issue-57979-impl-trait-in-path.stderr | 30 +- ...e-57979-nested-impl-trait-in-assoc-proj.rs | 35 +- ...979-nested-impl-trait-in-assoc-proj.stderr | 42 +- .../error-handling.polonius.stderr | 12 + .../multiple-lifetimes/error-handling.stderr | 1 + ...t_outlive_least_region_or_bound.nll.stderr | 4 + .../must_outlive_least_region_or_bound.stderr | 3 +- .../static-return-lifetime-infered.nll.stderr | 1 + src/test/ui/impl-trait/trait_type.stderr | 6 +- .../ui/impl-trait/type-alias-generic-param.rs | 22 + .../universal-mismatched-type.stderr | 10 +- .../universal-two-impl-traits.stderr | 11 +- src/test/ui/impl-trait/where-allowed-2.rs | 9 + src/test/ui/impl-trait/where-allowed-2.stderr | 11 + src/test/ui/impl-trait/where-allowed.rs | 6 +- src/test/ui/impl-trait/where-allowed.stderr | 113 +- ...elude-extern-crate-restricted-shadowing.rs | 3 +- ...e-extern-crate-restricted-shadowing.stderr | 6 +- .../ui/imports/import-prefix-macro-1.stderr | 2 +- src/test/ui/imports/issue-53140.rs | 2 +- src/test/ui/imports/issue-55811.rs | 2 +- src/test/ui/imports/issue-56263.rs | 2 +- .../in-band-lifetimes/mismatched.nll.stderr | 2 + .../ui/in-band-lifetimes/mismatched.stderr | 3 +- .../mismatched_trait_impl-2.rs | 3 +- .../mismatched_trait_impl-2.stderr | 2 +- .../mismatched_trait_impl.stderr | 1 + .../ui/include-macros/mismatched-types.stderr | 16 +- src/test/ui/indexing-requires-a-uint.stderr | 2 +- .../inference-variable-behind-raw-pointer.rs | 4 +- .../infinite/infinite-recursion-const-fn.rs | 2 +- .../infinite-recursion-const-fn.stderr | 69 +- src/test/ui/inline-asm-bad-constraint.stderr | 1 + src/test/ui/inline-asm-bad-operand.stderr | 1 + .../ui/integer-literal-suffix-inference.rs | 72 +- .../integer-literal-suffix-inference.stderr | 72 +- .../ui/integral-variable-unification-error.rs | 2 - ...integral-variable-unification-error.stderr | 3 - .../interior-mutability.rs | 3 +- .../interior-mutability.stderr | 4 +- .../invalid/invalid-variadic-function.stderr | 2 +- src/test/ui/invalid_const_promotion.rs | 9 +- .../ui/issues/auxiliary/issue-38715-modern.rs | 7 - src/test/ui/issues/auxiliary/issue-38715.rs | 7 - src/test/ui/issues/issue-10176.rs | 4 +- src/test/ui/issues/issue-10176.stderr | 4 +- src/test/ui/issues/issue-10291.nll.stderr | 2 + src/test/ui/issues/issue-10396.rs | 2 +- src/test/ui/issues/issue-10456.rs | 2 +- src/test/ui/issues/issue-10536.rs | 4 +- src/test/ui/issues/issue-10536.stderr | 8 +- src/test/ui/issues/issue-10763.rs | 2 +- src/test/ui/issues/issue-10764.stderr | 4 +- src/test/ui/issues/issue-10853.rs | 2 +- src/test/ui/issues/issue-10902.rs | 2 +- src/test/ui/issues/issue-11319.rs | 3 +- src/test/ui/issues/issue-11319.stderr | 5 +- src/test/ui/issues/issue-11374.stderr | 6 +- src/test/ui/issues/issue-11384.rs | 2 +- src/test/ui/issues/issue-11515.stderr | 4 +- src/test/ui/issues/issue-11592.rs | 2 +- src/test/ui/issues/issue-11612.rs | 2 +- src/test/ui/issues/issue-11844.stderr | 4 +- src/test/ui/issues/issue-11869.rs | 2 +- src/test/ui/issues/issue-12028.stderr | 6 +- src/test/ui/issues/issue-1251.rs | 2 +- src/test/ui/issues/issue-12552.stderr | 8 +- src/test/ui/issues/issue-12567.stderr | 18 +- src/test/ui/issues/issue-12729.rs | 2 +- src/test/ui/issues/issue-12997-2.stderr | 5 +- src/test/ui/issues/issue-13033.rs | 4 +- src/test/ui/issues/issue-13033.stderr | 4 +- src/test/ui/issues/issue-13105.rs | 2 +- src/test/ui/issues/issue-13167.rs | 2 +- src/test/ui/issues/issue-13214.rs | 2 +- src/test/ui/issues/issue-13359.rs | 4 +- src/test/ui/issues/issue-13359.stderr | 4 +- src/test/ui/issues/issue-13405.rs | 2 +- src/test/ui/issues/issue-13407.stderr | 3 - src/test/ui/issues/issue-13446.stderr | 6 +- src/test/ui/issues/issue-13466.rs | 8 +- src/test/ui/issues/issue-13466.stderr | 8 +- src/test/ui/issues/issue-1362.stderr | 4 +- src/test/ui/issues/issue-13703.rs | 2 +- src/test/ui/issues/issue-13775.rs | 2 +- src/test/ui/issues/issue-13837.rs | 2 +- src/test/ui/issues/issue-13853.stderr | 12 +- src/test/ui/issues/issue-14082.rs | 2 +- src/test/ui/issues/issue-14091.stderr | 5 +- src/test/ui/issues/issue-14227.rs | 5 +- src/test/ui/issues/issue-14227.stderr | 10 +- src/test/ui/issues/issue-14254.rs | 2 +- src/test/ui/issues/issue-14330.rs | 2 +- src/test/ui/issues/issue-1448-2.stderr | 2 +- src/test/ui/issues/issue-14541.rs | 2 - src/test/ui/issues/issue-14541.stderr | 3 - src/test/ui/issues/issue-14837.rs | 2 +- src/test/ui/issues/issue-14901.rs | 2 +- src/test/ui/issues/issue-14933.rs | 2 +- src/test/ui/issues/issue-14936.rs | 2 +- src/test/ui/issues/issue-14959.rs | 2 +- src/test/ui/issues/issue-15094.rs | 4 +- src/test/ui/issues/issue-15094.stderr | 4 +- src/test/ui/issues/issue-15108.rs | 4 - src/test/ui/issues/issue-15261.rs | 2 +- src/test/ui/issues/issue-15689-2.rs | 2 +- src/test/ui/issues/issue-15735.rs | 2 +- src/test/ui/issues/issue-15783.rs | 6 +- src/test/ui/issues/issue-15783.stderr | 6 +- src/test/ui/issues/issue-15896.rs | 2 - src/test/ui/issues/issue-15896.stderr | 3 - src/test/ui/issues/issue-16338.rs | 2 +- src/test/ui/issues/issue-16338.stderr | 4 +- src/test/ui/issues/issue-16401.rs | 6 +- src/test/ui/issues/issue-16401.stderr | 6 +- src/test/ui/issues/issue-16538.rs | 3 +- src/test/ui/issues/issue-16538.stderr | 16 +- src/test/ui/issues/issue-16596.rs | 2 +- src/test/ui/issues/issue-16668.rs | 2 +- src/test/ui/issues/issue-16683.stderr | 10 +- src/test/ui/issues/issue-16966.stderr | 2 +- src/test/ui/issues/issue-17033.rs | 4 +- src/test/ui/issues/issue-17033.stderr | 5 +- src/test/ui/issues/issue-17121.rs | 2 +- src/test/ui/issues/issue-17263.rs | 2 +- src/test/ui/issues/issue-17336.rs | 2 +- src/test/ui/issues/issue-17450.rs | 2 +- src/test/ui/issues/issue-17551.stderr | 2 +- .../issue-17718-const-bad-values.stderr | 20 +- .../issues/issue-17718-const-destructors.rs | 2 +- .../ui/issues/issue-17718-references.stderr | 4 +- src/test/ui/issues/issue-17728.nll.stderr | 4 +- src/test/ui/issues/issue-17728.stderr | 7 +- src/test/ui/issues/issue-17732.rs | 2 +- src/test/ui/issues/issue-17740.rs | 8 +- src/test/ui/issues/issue-17740.stderr | 8 +- src/test/ui/issues/issue-17746.rs | 2 +- src/test/ui/issues/issue-17758.stderr | 10 +- src/test/ui/issues/issue-17904.rs | 2 +- src/test/ui/issues/issue-17905-2.stderr | 8 +- src/test/ui/issues/issue-18083.rs | 2 +- src/test/ui/issues/issue-18088.rs | 2 +- src/test/ui/issues/issue-18118-2.stderr | 4 +- src/test/ui/issues/issue-18188.rs | 2 +- src/test/ui/issues/issue-1821.rs | 2 +- src/test/ui/issues/issue-18446-2.rs | 2 +- src/test/ui/issues/issue-1866.rs | 2 +- src/test/ui/issues/issue-18738.rs | 2 +- src/test/ui/issues/issue-18809.rs | 2 +- src/test/ui/issues/issue-18906.rs | 2 +- src/test/ui/issues/issue-18988.rs | 2 +- src/test/ui/issues/issue-19037.rs | 2 +- src/test/ui/issues/issue-19081.rs | 2 +- src/test/ui/issues/issue-19097.rs | 2 +- src/test/ui/issues/issue-19098.rs | 2 +- src/test/ui/issues/issue-19102.rs | 2 +- src/test/ui/issues/issue-19129-1.rs | 2 +- src/test/ui/issues/issue-19129-2.rs | 2 +- src/test/ui/issues/issue-19398.rs | 2 +- src/test/ui/issues/issue-19404.rs | 2 +- src/test/ui/issues/issue-19479.rs | 2 +- src/test/ui/issues/issue-19631.rs | 2 +- src/test/ui/issues/issue-19632.rs | 2 +- src/test/ui/issues/issue-19850.rs | 2 +- src/test/ui/issues/issue-19982.rs | 2 +- src/test/ui/issues/issue-19991.rs | 4 +- src/test/ui/issues/issue-19991.stderr | 6 +- src/test/ui/issues/issue-20009.rs | 2 +- src/test/ui/issues/issue-20091.rs | 2 +- src/test/ui/issues/issue-20186.rs | 2 +- src/test/ui/issues/issue-20225.rs | 3 - src/test/ui/issues/issue-20225.stderr | 29 +- src/test/ui/issues/issue-20396.rs | 2 +- src/test/ui/issues/issue-20414.rs | 2 +- src/test/ui/issues/issue-20454.rs | 2 +- src/test/ui/issues/issue-20616-1.stderr | 2 +- src/test/ui/issues/issue-20616-2.stderr | 2 +- src/test/ui/issues/issue-20616-3.stderr | 2 +- src/test/ui/issues/issue-20616-4.stderr | 2 +- src/test/ui/issues/issue-20616-5.stderr | 2 +- src/test/ui/issues/issue-20616-6.stderr | 2 +- src/test/ui/issues/issue-20616-7.stderr | 2 +- src/test/ui/issues/issue-20616-8.stderr | 2 +- src/test/ui/issues/issue-20616-9.stderr | 2 +- src/test/ui/issues/issue-2063-resource.rs | 2 +- src/test/ui/issues/issue-20644.rs | 2 +- src/test/ui/issues/issue-20763-1.rs | 2 +- src/test/ui/issues/issue-20763-2.rs | 2 +- src/test/ui/issues/issue-20797.rs | 2 +- src/test/ui/issues/issue-20825-2.rs | 2 +- .../ui/issues/issue-20831-debruijn.stderr | 16 +- src/test/ui/issues/issue-21140.rs | 2 +- src/test/ui/issues/issue-21146.stderr | 2 +- src/test/ui/issues/issue-21160.rs | 3 +- src/test/ui/issues/issue-21160.stderr | 2 +- src/test/ui/issues/issue-21174-2.rs | 2 +- src/test/ui/issues/issue-21245.rs | 2 +- src/test/ui/issues/issue-21332.stderr | 4 +- src/test/ui/issues/issue-21363.rs | 2 +- src/test/ui/issues/issue-21402.rs | 2 +- src/test/ui/issues/issue-21520.rs | 2 +- src/test/ui/issues/issue-21562.rs | 2 +- src/test/ui/issues/issue-21622.rs | 2 +- src/test/ui/issues/issue-21634.rs | 2 +- src/test/ui/issues/issue-21726.rs | 2 +- src/test/ui/issues/issue-21891.rs | 2 +- src/test/ui/issues/issue-21974.stderr | 6 +- src/test/ui/issues/issue-22066.rs | 2 +- src/test/ui/issues/issue-2216.rs | 2 +- src/test/ui/issues/issue-22356.rs | 2 +- src/test/ui/issues/issue-22375.rs | 2 +- src/test/ui/issues/issue-22471.rs | 2 +- src/test/ui/issues/issue-22684.stderr | 7 +- src/test/ui/issues/issue-22777.rs | 2 +- src/test/ui/issues/issue-22781.rs | 2 +- src/test/ui/issues/issue-22814.rs | 2 +- src/test/ui/issues/issue-22894.rs | 2 +- src/test/ui/issues/issue-2311-2.rs | 2 +- src/test/ui/issues/issue-2311.rs | 2 +- src/test/ui/issues/issue-2312.rs | 2 +- src/test/ui/issues/issue-23406.rs | 2 +- src/test/ui/issues/issue-23442.rs | 2 +- src/test/ui/issues/issue-23550.rs | 2 +- src/test/ui/issues/issue-23589.stderr | 5 +- src/test/ui/issues/issue-23649-3.rs | 2 +- src/test/ui/issues/issue-24036.stderr | 6 +- src/test/ui/issues/issue-24085.rs | 2 +- src/test/ui/issues/issue-24161.rs | 2 +- src/test/ui/issues/issue-24204.stderr | 6 +- src/test/ui/issues/issue-24227.rs | 2 +- src/test/ui/issues/issue-24322.stderr | 8 +- src/test/ui/issues/issue-24338.rs | 2 +- src/test/ui/issues/issue-24389.rs | 2 +- src/test/ui/issues/issue-24424.rs | 2 +- src/test/ui/issues/issue-24424.stderr | 6 +- src/test/ui/issues/issue-24434.rs | 2 +- src/test/ui/issues/issue-24819.stderr | 4 +- src/test/ui/issues/issue-2487-a.rs | 2 +- src/test/ui/issues/issue-2502.rs | 2 +- src/test/ui/issues/issue-25180.rs | 2 +- src/test/ui/issues/issue-25368.stderr | 2 +- src/test/ui/issues/issue-25394.rs | 2 +- src/test/ui/issues/issue-25579.rs | 2 +- src/test/ui/issues/issue-26095.rs | 2 +- src/test/ui/issues/issue-2611-3.rs | 2 +- src/test/ui/issues/issue-26205.rs | 2 +- src/test/ui/issues/issue-26217.nll.stderr | 2 + src/test/ui/issues/issue-26646.rs | 2 +- src/test/ui/issues/issue-26997.rs | 2 +- src/test/ui/issues/issue-27008.rs | 4 +- src/test/ui/issues/issue-27008.stderr | 5 +- src/test/ui/issues/issue-27033.rs | 3 +- src/test/ui/issues/issue-27033.stderr | 8 +- src/test/ui/issues/issue-27042.stderr | 24 +- src/test/ui/issues/issue-27105.rs | 2 +- src/test/ui/issues/issue-27281.rs | 2 +- src/test/ui/issues/issue-2748-a.rs | 2 +- src/test/ui/issues/issue-27583.rs | 2 +- src/test/ui/issues/issue-27889.rs | 2 +- src/test/ui/issues/issue-2804-2.rs | 2 +- src/test/ui/issues/issue-28279.rs | 2 +- src/test/ui/issues/issue-28324.rs | 5 +- src/test/ui/issues/issue-28324.stderr | 10 +- src/test/ui/issues/issue-28433.stderr | 9 +- src/test/ui/issues/issue-28561.rs | 2 +- src/test/ui/issues/issue-28600.rs | 2 +- src/test/ui/issues/issue-28822.rs | 2 +- src/test/ui/issues/issue-28848.nll.stderr | 2 + src/test/ui/issues/issue-28871.rs | 2 +- src/test/ui/issues/issue-28936.rs | 2 +- src/test/ui/issues/issue-28999.rs | 2 +- src/test/ui/issues/issue-29030.rs | 2 +- src/test/ui/issues/issue-29037.rs | 2 +- src/test/ui/issues/issue-2904.rs | 2 +- src/test/ui/issues/issue-29048.rs | 2 +- src/test/ui/issues/issue-29071.rs | 2 +- src/test/ui/issues/issue-29084.rs | 4 +- src/test/ui/issues/issue-29084.stderr | 5 +- src/test/ui/issues/issue-29147.rs | 2 +- src/test/ui/issues/issue-29147.stderr | 6 +- src/test/ui/issues/issue-29276.rs | 2 +- src/test/ui/issues/issue-2951.rs | 6 +- src/test/ui/issues/issue-2951.stderr | 11 +- src/test/ui/issues/issue-29516.rs | 2 +- src/test/ui/issues/issue-29540.rs | 2 +- src/test/ui/issues/issue-29710.rs | 2 +- src/test/ui/issues/issue-29740.rs | 2 +- src/test/ui/issues/issue-29743.rs | 3 +- src/test/ui/issues/issue-30225.stderr | 3 - src/test/ui/issues/issue-31173.rs | 2 +- src/test/ui/issues/issue-31173.stderr | 6 +- src/test/ui/issues/issue-31260.rs | 2 +- src/test/ui/issues/issue-3149.rs | 2 +- src/test/ui/issues/issue-31597.rs | 2 +- src/test/ui/issues/issue-31910.rs | 2 +- src/test/ui/issues/issue-31910.stderr | 2 +- src/test/ui/issues/issue-32323.stderr | 6 +- src/test/ui/issues/issue-32324.rs | 2 +- src/test/ui/issues/issue-32995-2.rs | 5 - src/test/ui/issues/issue-32995-2.stderr | 29 +- src/test/ui/issues/issue-32995.rs | 9 - src/test/ui/issues/issue-32995.stderr | 65 +- .../issues/issue-33140-traitobject-crate.rs | 8 +- .../issue-33140-traitobject-crate.stderr | 7 +- src/test/ui/issues/issue-33264.rs | 2 +- src/test/ui/issues/issue-33287.rs | 2 +- src/test/ui/issues/issue-3344.stderr | 2 +- src/test/ui/issues/issue-33504.stderr | 3 - src/test/ui/issues/issue-33903.rs | 2 +- src/test/ui/issues/issue-33941.stderr | 8 +- src/test/ui/issues/issue-34194.rs | 2 +- src/test/ui/issues/issue-3424.rs | 2 +- src/test/ui/issues/issue-34334.stderr | 6 +- src/test/ui/issues/issue-34721.fixed | 34 + src/test/ui/issues/issue-34721.rs | 2 + src/test/ui/issues/issue-34721.stderr | 6 +- src/test/ui/issues/issue-34751.rs | 2 +- src/test/ui/issues/issue-3477.rs | 2 +- src/test/ui/issues/issue-3477.stderr | 4 +- src/test/ui/issues/issue-34780.rs | 2 +- src/test/ui/issues/issue-35241.stderr | 4 +- src/test/ui/issues/issue-35376.rs | 2 +- src/test/ui/issues/issue-35546.rs | 2 +- src/test/ui/issues/issue-3563-2.rs | 2 +- src/test/ui/issues/issue-35869.stderr | 24 +- src/test/ui/issues/issue-3601.stderr | 4 +- src/test/ui/issues/issue-36075.rs | 2 +- src/test/ui/issues/issue-3609.rs | 2 +- .../ui/issues/issue-36744-without-calls.rs | 2 +- src/test/ui/issues/issue-3680.rs | 4 +- src/test/ui/issues/issue-3680.stderr | 4 +- src/test/ui/issues/issue-37026.stderr | 10 +- src/test/ui/issues/issue-37323.rs | 3 +- src/test/ui/issues/issue-37433.stderr | 1 + src/test/ui/issues/issue-37655.rs | 2 +- src/test/ui/issues/issue-37665.stderr | 7 +- src/test/ui/issues/issue-37725.rs | 2 +- src/test/ui/issues/issue-37733.rs | 2 +- src/test/ui/issues/issue-37884.stderr | 4 +- src/test/ui/issues/issue-38715-rpass.rs | 15 - src/test/ui/issues/issue-38715.rs | 1 - src/test/ui/issues/issue-38715.stderr | 3 - src/test/ui/issues/issue-38727.rs | 2 +- src/test/ui/issues/issue-3874.rs | 2 +- src/test/ui/issues/issue-38875/issue-38875.rs | 2 +- src/test/ui/issues/issue-3888-2.rs | 2 +- src/test/ui/issues/issue-38940.stderr | 8 +- src/test/ui/issues/issue-39089.rs | 2 +- src/test/ui/issues/issue-39467.rs | 2 +- src/test/ui/issues/issue-39616.stderr | 2 +- src/test/ui/issues/issue-39720.rs | 4 +- src/test/ui/issues/issue-3979-2.rs | 2 +- src/test/ui/issues/issue-39848.stderr | 2 +- src/test/ui/issues/issue-3991.rs | 2 +- src/test/ui/issues/issue-39970.stderr | 4 +- src/test/ui/issues/issue-39974.rs | 2 +- src/test/ui/issues/issue-39974.stderr | 2 +- src/test/ui/issues/issue-39984.rs | 2 +- src/test/ui/issues/issue-40000.stderr | 4 +- src/test/ui/issues/issue-40136.rs | 2 +- src/test/ui/issues/issue-40231-1.rs | 54 + src/test/ui/issues/issue-40231-2.rs | 54 + src/test/ui/issues/issue-4025.rs | 2 +- .../issue-40402-2.stderr | 6 +- src/test/ui/issues/issue-40510-2.rs | 2 +- src/test/ui/issues/issue-40510-4.rs | 2 +- src/test/ui/issues/issue-40749.rs | 2 +- src/test/ui/issues/issue-40749.stderr | 4 +- src/test/ui/issues/issue-40962.rs | 2 +- src/test/ui/issues/issue-41272.rs | 2 +- src/test/ui/issues/issue-41298.rs | 2 +- src/test/ui/issues/issue-41549.stderr | 5 +- src/test/ui/issues/issue-41628.rs | 2 +- src/test/ui/issues/issue-41742.stderr | 5 +- ...sue-41936-variance-coerce-unsized-cycle.rs | 2 +- src/test/ui/issues/issue-41974.stderr | 1 + src/test/ui/issues/issue-41998.rs | 2 +- src/test/ui/issues/issue-4201.rs | 4 +- src/test/ui/issues/issue-4201.stderr | 6 +- src/test/ui/issues/issue-42467.rs | 2 +- src/test/ui/issues/issue-42956.rs | 2 +- src/test/ui/issues/issue-43057.rs | 2 +- src/test/ui/issues/issue-43162.stderr | 5 +- src/test/ui/issues/issue-4335.rs | 3 +- src/test/ui/issues/issue-4335.stderr | 23 +- src/test/ui/issues/issue-43357.rs | 2 +- src/test/ui/issues/issue-43398.rs | 8 +- .../issues/issue-43420-no-over-suggest.stderr | 6 +- src/test/ui/issues/issue-43483.rs | 2 +- src/test/ui/issues/issue-43623.stderr | 3 +- src/test/ui/issues/issue-43988.stderr | 4 +- src/test/ui/issues/issue-44005.rs | 2 +- src/test/ui/issues/issue-44021.stderr | 2 +- src/test/ui/issues/issue-44023.stderr | 5 +- src/test/ui/issues/issue-44056.rs | 2 +- src/test/ui/issues/issue-44247.rs | 2 +- src/test/ui/issues/issue-44373-2.rs | 2 +- src/test/ui/issues/issue-4464.rs | 2 +- src/test/ui/issues/issue-44730.rs | 2 +- src/test/ui/issues/issue-44851.rs | 2 +- src/test/ui/issues/issue-4517.rs | 4 +- src/test/ui/issues/issue-4517.stderr | 5 +- src/test/ui/issues/issue-45425.rs | 2 +- src/test/ui/issues/issue-45730.stderr | 1 + src/test/ui/issues/issue-46023.stderr | 1 + src/test/ui/issues/issue-46112.stderr | 6 +- src/test/ui/issues/issue-46302.stderr | 5 +- src/test/ui/issues/issue-46604.rs | 2 +- src/test/ui/issues/issue-46604.stderr | 8 +- ...-consider-borrowing-cast-or-binexpr.stderr | 10 +- src/test/ui/issues/issue-46843.rs | 14 - src/test/ui/issues/issue-46843.stderr | 22 - src/test/ui/issues/issue-46959.rs | 2 +- src/test/ui/issues/issue-46964.rs | 2 +- src/test/ui/issues/issue-47094.rs | 6 +- src/test/ui/issues/issue-47309.rs | 2 +- src/test/ui/issues/issue-47486.stderr | 5 +- src/test/ui/issues/issue-47673.rs | 2 +- src/test/ui/issues/issue-47703-1.rs | 2 +- src/test/ui/issues/issue-47703-tuple.rs | 2 +- src/test/ui/issues/issue-47703.rs | 2 +- src/test/ui/issues/issue-47722.rs | 2 +- src/test/ui/issues/issue-47789.rs | 2 +- src/test/ui/issues/issue-4830.rs | 2 +- src/test/ui/issues/issue-48364.stderr | 6 +- src/test/ui/issues/issue-48551.rs | 2 +- src/test/ui/issues/issue-48838.stderr | 4 +- src/test/ui/issues/issue-49556.rs | 2 +- src/test/ui/issues/issue-49579.rs | 2 +- src/test/ui/issues/issue-4968.rs | 2 +- src/test/ui/issues/issue-4968.stderr | 2 +- src/test/ui/issues/issue-50187.rs | 2 +- src/test/ui/issues/issue-50411.rs | 2 +- src/test/ui/issues/issue-50471.rs | 2 +- src/test/ui/issues/issue-50518.rs | 2 +- src/test/ui/issues/issue-50577.rs | 6 - src/test/ui/issues/issue-50582.rs | 1 + src/test/ui/issues/issue-50582.stderr | 11 +- src/test/ui/issues/issue-50585.rs | 1 + src/test/ui/issues/issue-50585.stderr | 16 +- src/test/ui/issues/issue-50600.stderr | 4 +- src/test/ui/issues/issue-5062.stderr | 2 +- src/test/ui/issues/issue-50688.stderr | 4 +- src/test/ui/issues/issue-50761.rs | 2 +- src/test/ui/issues/issue-50993.rs | 2 +- src/test/ui/issues/issue-5100.rs | 22 +- src/test/ui/issues/issue-5100.stderr | 24 +- src/test/ui/issues/issue-51244.stderr | 1 + src/test/ui/issues/issue-51515.stderr | 1 + src/test/ui/issues/issue-51582.rs | 2 +- ...1632-try-desugar-incompatible-types.stderr | 15 +- src/test/ui/issues/issue-51655.rs | 2 +- src/test/ui/issues/issue-51714.rs | 1 + src/test/ui/issues/issue-51714.stderr | 15 +- src/test/ui/issues/issue-51947.rs | 2 +- src/test/ui/issues/issue-52057.rs | 1 - src/test/ui/issues/issue-52057.stderr | 8 - src/test/ui/issues/issue-5216.stderr | 8 +- src/test/ui/issues/issue-52213.nll.stderr | 2 + src/test/ui/issues/issue-52213.stderr | 10 +- src/test/ui/issues/issue-52496.stderr | 2 +- src/test/ui/issues/issue-52533-1.stderr | 4 +- src/test/ui/issues/issue-52992.rs | 2 +- src/test/ui/issues/issue-53348.rs | 3 +- src/test/ui/issues/issue-53348.stderr | 5 +- src/test/ui/issues/issue-53419.rs | 2 +- src/test/ui/issues/issue-5353.rs | 2 +- src/test/ui/issues/issue-53568.rs | 2 +- src/test/ui/issues/issue-5358-1.rs | 4 +- src/test/ui/issues/issue-5358-1.stderr | 4 +- .../issues/issue-53675-a-test-called-panic.rs | 2 +- src/test/ui/issues/issue-53692.stderr | 25 +- .../issue-53787-inline-assembler-macro.stderr | 1 + src/test/ui/issues/issue-53912.rs | 2 +- src/test/ui/issues/issue-54348.rs | 2 - src/test/ui/issues/issue-54348.stderr | 16 +- src/test/ui/issues/issue-54387.rs | 2 +- src/test/ui/issues/issue-54521-1.rs | 2 +- src/test/ui/issues/issue-54943-1.rs | 2 +- src/test/ui/issues/issue-54943-2.rs | 2 +- src/test/ui/issues/issue-54943-3.rs | 2 +- src/test/ui/issues/issue-54943.nll.stderr | 2 + src/test/ui/issues/issue-54954.stderr | 6 +- src/test/ui/issues/issue-5500-1.rs | 2 +- src/test/ui/issues/issue-5572.rs | 2 +- src/test/ui/issues/issue-55796.nll.stderr | 4 + src/test/ui/issues/issue-55796.stderr | 20 +- src/test/ui/issues/issue-56128.rs | 2 +- src/test/ui/issues/issue-56202.rs | 2 +- src/test/ui/issues/issue-56411-aux.rs | 2 +- src/test/ui/issues/issue-56943.stderr | 7 +- src/test/ui/issues/issue-57156.rs | 2 +- src/test/ui/issues/issue-57162.rs | 2 +- .../issue-57399-self-return-impl-trait.rs | 2 +- .../issue-57399-self-return-impl-trait.stderr | 8 - src/test/ui/issues/issue-57410-1.rs | 2 +- src/test/ui/issues/issue-57410.rs | 2 +- src/test/ui/issues/issue-5754.rs | 2 +- src/test/ui/issues/issue-57741-1.stderr | 8 +- src/test/ui/issues/issue-57741.stderr | 16 +- src/test/ui/issues/issue-58022.rs | 2 +- src/test/ui/issues/issue-58022.stderr | 6 +- src/test/ui/issues/issue-5884.rs | 2 +- src/test/ui/issues/issue-58856-2.stderr | 2 +- src/test/ui/issues/issue-5900.rs | 2 +- src/test/ui/issues/issue-59488.stderr | 12 +- src/test/ui/issues/issue-5950.rs | 2 +- src/test/ui/issues/issue-59756.rs | 4 + src/test/ui/issues/issue-59756.stderr | 17 +- src/test/ui/issues/issue-60075.rs | 2 +- src/test/ui/issues/issue-60075.stderr | 4 +- src/test/ui/issues/issue-60283.stderr | 3 +- src/test/ui/issues/issue-60662.rs | 2 +- src/test/ui/issues/issue-60662.stdout | 2 +- src/test/ui/issues/issue-61106.stderr | 5 +- src/test/ui/issues/issue-61882.stderr | 11 +- src/test/ui/issues/issue-62480.rs | 10 + src/test/ui/issues/issue-62480.stderr | 8 + src/test/ui/issues/issue-6341.rs | 2 +- src/test/ui/issues/issue-6458-2.stderr | 2 +- src/test/ui/issues/issue-6458-3.stderr | 2 +- src/test/ui/issues/issue-6458-4.stderr | 6 +- src/test/ui/issues/issue-6458.stderr | 2 +- src/test/ui/issues/issue-6470.rs | 2 +- src/test/ui/issues/issue-6557.rs | 2 +- src/test/ui/issues/issue-65611.stderr | 5 +- .../issue-65634-raw-ident-suggestion.rs | 22 + .../issue-65634-raw-ident-suggestion.stderr | 22 + .../issue-66702-break-outside-loop-val.rs | 7 + .../issue-66702-break-outside-loop-val.stderr | 11 + src/test/ui/issues/issue-66851.rs | 20 + ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 4 +- .../issue-67039-unsound-pin-partialeq.rs | 27 + .../issue-67039-unsound-pin-partialeq.stderr | 13 + ...68000-unicode-ident-after-missing-comma.rs | 6 + ...0-unicode-ident-after-missing-comma.stderr | 17 + .../issue-68091-unicode-ident-after-if.rs | 9 + .../issue-68091-unicode-ident-after-if.stderr | 8 + ...092-unicode-ident-after-incomplete-expr.rs | 9 + ...unicode-ident-after-incomplete-expr.stderr | 8 + src/test/ui/issues/issue-6898.rs | 2 +- .../issue-69225-SCEVAddExpr-wrap-flag.rs | 33 + ...issue-69225-layout-repeated-checked-add.rs | 31 + src/test/ui/issues/issue-6991.rs | 2 +- src/test/ui/issues/issue-7061.rs | 4 +- src/test/ui/issues/issue-7061.stderr | 6 +- src/test/ui/issues/issue-7092.rs | 4 +- src/test/ui/issues/issue-7092.stderr | 4 +- src/test/ui/issues/issue-7268.rs | 2 +- src/test/ui/issues/issue-7607-2.rs | 2 +- ...7673-cast-generically-implemented-trait.rs | 2 +- src/test/ui/issues/issue-7867.rs | 4 +- src/test/ui/issues/issue-7867.stderr | 4 +- ...fault-method-self-inherit-builtin-trait.rs | 2 +- src/test/ui/issues/issue-8398.rs | 2 +- src/test/ui/issues/issue-8460-const.rs | 10 - src/test/ui/issues/issue-8460-const.stderr | 100 +- src/test/ui/issues/issue-8460-const2.rs | 10 - src/test/ui/issues/issue-8460-const2.stderr | 90 +- src/test/ui/issues/issue-8521.rs | 2 +- src/test/ui/issues/issue-8578.rs | 2 +- src/test/ui/issues/issue-8761.rs | 4 +- src/test/ui/issues/issue-8761.stderr | 4 +- src/test/ui/issues/issue-9110.rs | 2 +- src/test/ui/issues/issue-9243.rs | 2 +- src/test/ui/issues/issue-9249.rs | 2 +- src/test/ui/issues/issue-9575.stderr | 4 +- src/test/ui/issues/issue-9719.rs | 2 +- .../iterators/into-iter-on-arrays-lint.fixed | 33 + .../ui/iterators/into-iter-on-arrays-lint.rs | 33 + .../iterators/into-iter-on-arrays-lint.stderr | 37 + .../ui/json-bom-plus-crlf-multifile.stderr | 24 +- src/test/ui/json-bom-plus-crlf.stderr | 24 +- src/test/ui/json-short.stderr | 3 +- .../keyword-false-as-identifier.stderr | 5 +- .../keyword/keyword-true-as-identifier.stderr | 5 +- .../ui/kindck/kindck-impl-type-params-2.rs | 2 +- .../kindck/kindck-impl-type-params-2.stderr | 2 +- .../kindck-inherited-copy-bound.curr.stderr | 2 +- ...copy-bound.object_safe_for_dispatch.stderr | 2 +- .../label/label-beginning-with-underscore.rs | 10 + .../label/label_break_value_continue.stderr | 9 +- .../label_break_value_illegal_uses.stderr | 4 +- .../homogeneous-aggr-zero-sized-c-struct.rs | 2 +- ...etime-bound-will-change-warning.nll.stderr | 4 + .../lifetime-bound-will-change-warning.stderr | 8 +- ...ne-existing-name-if-else-using-impl.stderr | 1 + ...e-existing-name-return-type-is-anon.stderr | 1 + ...turn-one-existing-name-self-is-anon.stderr | 1 + .../ex2b-push-no-existing-names.stderr | 1 + .../ex2c-push-inference-variable.nll.stderr | 2 + .../ex2c-push-inference-variable.stderr | 1 + .../ex2d-push-inference-variable-2.nll.stderr | 2 + .../ex2d-push-inference-variable-2.stderr | 1 + .../ex2e-push-inference-variable-3.nll.stderr | 2 + .../ex2e-push-inference-variable-3.stderr | 1 + .../ex3-both-anon-regions-2.stderr | 1 + .../ex3-both-anon-regions-3.stderr | 1 + ...oth-anon-regions-both-are-structs-2.stderr | 1 + ...oth-anon-regions-both-are-structs-3.stderr | 1 + ...-are-structs-earlybound-regions.nll.stderr | 2 + ...both-are-structs-earlybound-regions.stderr | 1 + ...h-are-structs-latebound-regions.nll.stderr | 2 + ...-both-are-structs-latebound-regions.stderr | 1 + ...-both-anon-regions-both-are-structs.stderr | 1 + ...-anon-regions-latebound-regions.nll.stderr | 2 + ...both-anon-regions-latebound-regions.stderr | 1 + ...3-both-anon-regions-one-is-struct-2.stderr | 1 + ...3-both-anon-regions-one-is-struct-3.stderr | 1 + ...3-both-anon-regions-one-is-struct-4.stderr | 1 + ...ex3-both-anon-regions-one-is-struct.stderr | 1 + ...th-anon-regions-return-type-is-anon.stderr | 1 + .../ex3-both-anon-regions-self-is-anon.stderr | 1 + ...x3-both-anon-regions-using-fn-items.stderr | 1 + ...-both-anon-regions-using-impl-items.stderr | 1 + ...th-anon-regions-using-trait-objects.stderr | 1 + .../ex3-both-anon-regions.stderr | 1 + ...ure-doesnt-life-long-enough-issue-67634.rs | 3 + ...doesnt-life-long-enough-issue-67634.stderr | 15 + .../ui/lint/command-line-lint-group-warn.rs | 3 +- .../dead-code/alias-in-pat.rs} | 0 .../dead-code/associated-type.rs} | 0 .../dead-code/basic.rs} | 0 .../dead-code/basic.stderr} | 6 +- .../dead-code/closure-bang.rs} | 0 .../const-and-self.rs} | 0 .../empty-unused-enum.rs} | 0 .../empty-unused-enum.stderr} | 6 +- .../empty-unused-public-enum.rs} | 0 .../dead-code/enum-variants.rs} | 0 .../impl-trait.rs} | 0 .../impl-trait.stderr} | 4 +- .../dead-code/leading-underscore.rs} | 0 .../lint/{ => dead-code}/lint-dead-code-1.rs | 0 .../{ => dead-code}/lint-dead-code-1.stderr | 28 +- .../lint/{ => dead-code}/lint-dead-code-2.rs | 0 .../{ => dead-code}/lint-dead-code-2.stderr | 12 +- .../lint/{ => dead-code}/lint-dead-code-3.rs | 0 .../{ => dead-code}/lint-dead-code-3.stderr | 12 +- .../lint/{ => dead-code}/lint-dead-code-4.rs | 10 +- .../{ => dead-code}/lint-dead-code-4.stderr | 14 +- .../lint/{ => dead-code}/lint-dead-code-5.rs | 0 .../{ => dead-code}/lint-dead-code-5.stderr | 4 +- src/test/ui/lint/dead-code/newline-span.rs | 19 + .../ui/lint/dead-code/newline-span.stderr | 26 + .../dead-code/tuple-struct-field.rs} | 0 .../type-alias.rs} | 0 .../type-alias.stderr} | 4 +- .../unused-enum.rs} | 0 .../unused-enum.stderr} | 14 +- .../unused-struct-variant.rs} | 0 .../unused-struct-variant.stderr} | 4 +- .../unused-variant-pub.rs} | 0 .../unused-variant.rs} | 0 .../unused-variant.stderr} | 4 +- .../dead-code/with-core-crate.rs} | 0 .../dead-code/with-core-crate.stderr} | 6 +- .../dead-code/with-impl.rs} | 0 ...47390-unused-variable-in-struct-pattern.rs | 29 +- ...0-unused-variable-in-struct-pattern.stderr | 26 +- ...775-nested-macro-unnecessary-parens-arg.rs | 2 +- ...issue-54099-camel-case-underscore-types.rs | 2 +- src/test/ui/lint/lint-ctypes.rs | 7 + src/test/ui/lint/lint-ctypes.stderr | 27 +- src/test/ui/lint/must-use-ops.rs | 44 +- src/test/ui/lint/not_found.rs | 10 +- src/test/ui/lint/not_found.stderr | 4 +- src/test/ui/lint/uninitialized-zeroed.rs | 9 + src/test/ui/lint/uninitialized-zeroed.stderr | 129 +- src/test/ui/lint/unreachable_pub-pub_crate.rs | 29 +- .../ui/lint/unreachable_pub-pub_crate.stderr | 10 +- src/test/ui/lint/unreachable_pub.rs | 28 +- src/test/ui/lint/unreachable_pub.stderr | 26 +- .../lint/unused_import_warning_issue_45268.rs | 3 +- src/test/ui/lint/use_suggestion_json.stderr | 3 +- .../liveness-closure-require-ret.stderr | 5 +- .../ui/liveness/liveness-forgot-ret.stderr | 5 +- .../ui/liveness/liveness-issue-2163.stderr | 5 +- .../ui/liveness/liveness-missing-ret2.stderr | 5 +- .../liveness-return-last-stmt-semi.stderr | 20 +- src/test/ui/loops/loop-break-value.rs | 6 +- src/test/ui/loops/loop-break-value.stderr | 54 +- .../ui/loops/loop-labeled-break-value.stderr | 15 +- .../ui/loops/loop-properly-diverging-2.stderr | 5 +- src/test/ui/lub-glb/old-lub-glb-hr.stderr | 4 +- src/test/ui/lub-glb/old-lub-glb-object.stderr | 4 +- src/test/ui/lub-if.nll.stderr | 4 + src/test/ui/lub-match.nll.stderr | 4 + src/test/ui/macro_backtrace/main.stderr | 6 +- .../ui/macros/assert-trailing-junk.stderr | 4 +- src/test/ui/macros/issue-54441.stderr | 2 +- .../macros/macro-lifetime-used-with-labels.rs | 4 +- .../macro-multiple-matcher-bindings.stderr | 40 +- src/test/ui/macros/macro-path-prelude-pass.rs | 4 +- .../ui/macros/macro-path-prelude-pass.stderr | 8 - .../ui/macros/macro-reexport-removed.stderr | 8 +- src/test/ui/macros/macro-use-all-and-none.rs | 2 +- .../ui/macros/macros-nonfatal-errors.stderr | 1 + src/test/ui/macros/unknown-builtin.stderr | 4 +- src/test/ui/main-wrong-type.stderr | 4 +- .../ui/malformed/malformed-derive-entry.rs | 8 +- .../malformed/malformed-derive-entry.stderr | 27 +- src/test/ui/malformed/malformed-meta-delim.rs | 11 + .../ui/malformed/malformed-meta-delim.stderr | 24 + .../ui/malformed/malformed-plugin-1.stderr | 2 +- .../ui/malformed/malformed-plugin-2.stderr | 2 +- .../ui/malformed/malformed-plugin-3.stderr | 4 +- .../ui/malformed/malformed-regressions.rs | 26 +- .../ui/malformed/malformed-regressions.stderr | 24 +- .../ui/malformed/malformed-special-attrs.rs | 2 +- .../malformed/malformed-special-attrs.stderr | 8 +- .../match/match-arm-resolving-to-never.stderr | 4 +- src/test/ui/match/match-ill-type2.stderr | 2 +- src/test/ui/match/match-range-fail.rs | 11 +- src/test/ui/match/match-range-fail.stderr | 33 +- .../match/match-ref-mut-invariance.nll.stderr | 2 + .../ui/match/match-ref-mut-invariance.stderr | 4 +- .../match-ref-mut-let-invariance.nll.stderr | 2 + .../match/match-ref-mut-let-invariance.stderr | 4 +- src/test/ui/match/match-struct.rs | 2 - src/test/ui/match/match-struct.stderr | 3 - src/test/ui/match/match-tag-nullary.stderr | 3 - src/test/ui/match/match-tag-unary.stderr | 3 - src/test/ui/match/match-type-err-first-arm.rs | 11 +- .../ui/match/match-type-err-first-arm.stderr | 26 +- src/test/ui/maybe-bounds-where.stderr | 1 + .../meta-expected-error-correct-rev.a.stderr | 4 +- ...od-ambig-one-trait-unknown-int-type.stderr | 6 +- ...-same-trait-object-with-separate-params.rs | 10 +- ...e-trait-object-with-separate-params.stderr | 35 +- src/test/ui/methods/method-self-arg-1.rs | 8 +- src/test/ui/methods/method-self-arg-1.stderr | 11 +- src/test/ui/mir-unpretty.stderr | 7 +- src/test/ui/mir/issue66339.rs | 13 + src/test/ui/mir/mir_assign_eval_order.rs | 67 + src/test/ui/mismatched_types/E0053.stderr | 10 +- src/test/ui/mismatched_types/E0409.stderr | 5 +- src/test/ui/mismatched_types/E0631.stderr | 1 + src/test/ui/mismatched_types/abridged.stderr | 40 +- .../closure-arg-type-mismatch.stderr | 3 +- .../mismatched_types/closure-mismatch.stderr | 3 +- .../ui/mismatched_types/fn-variance-1.stderr | 1 + .../for-loop-has-unit-body.stderr | 5 +- .../ui/mismatched_types/issue-19109.stderr | 6 +- .../ui/mismatched_types/issue-26480.stderr | 2 +- .../ui/mismatched_types/issue-35030.stderr | 9 +- .../ui/mismatched_types/issue-36053-2.stderr | 3 +- .../ui/mismatched_types/issue-38371.stderr | 16 +- src/test/ui/mismatched_types/main.stderr | 9 +- .../numeric-literal-cast.stderr | 6 +- .../overloaded-calls-bad.stderr | 5 +- .../mismatched_types/recovered-block.stderr | 2 +- .../trait-bounds-cant-coerce.stderr | 4 +- .../trait-impl-fn-incompatibility.stderr | 10 +- .../unboxed-closures-vtable-mismatch.stderr | 1 + .../ui/missing/missing-comma-in-match.fixed | 2 +- src/test/ui/missing/missing-comma-in-match.rs | 2 +- .../ui/missing/missing-comma-in-match.stderr | 2 +- src/test/ui/missing/missing-items/m2.stderr | 6 +- .../missing-type-parameter.stderr | 2 +- src/test/ui/missing/missing-return.stderr | 5 +- ...-on-type-no-recursive-stack-closure.stderr | 6 +- src/test/ui/mut/mut-cross-borrowing.stderr | 6 +- src/test/ui/mut/mut-pattern-mismatched.rs | 8 +- src/test/ui/mut/mut-pattern-mismatched.stderr | 8 +- src/test/ui/mut/mutable-class-fields-2.stderr | 1 + src/test/ui/mut/mutable-class-fields.stderr | 1 + src/test/ui/never_type/auto-traits.rs | 17 + .../call-fn-never-arg-wrong-type.stderr | 6 +- .../ui/never_type/defaulted-never-note.rs | 6 +- .../diverging-fallback-control-flow.rs | 2 +- .../feature-gate-never_type_fallback.rs | 12 + .../feature-gate-never_type_fallback.stderr | 11 + .../never_type/never-assign-wrong-type.stderr | 8 +- .../never-value-fallback-issue-66757.rs | 29 + src/test/ui/nll/closure-captures.stderr | 3 +- .../escape-argument-callee.stderr | 6 +- .../escape-argument.stderr | 6 +- .../escape-upvar-nested.stderr | 6 +- .../escape-upvar-ref.stderr | 4 +- .../issue-58127-mutliple-requirements.rs | 2 +- ...pagate-approximated-fail-no-postdom.stderr | 6 +- .../propagate-approximated-ref.stderr | 8 +- ...er-to-static-comparing-against-free.stderr | 12 +- ...oximated-shorter-to-static-no-bound.stderr | 8 +- ...mated-shorter-to-static-wrong-bound.stderr | 8 +- .../propagate-approximated-val.stderr | 8 +- .../propagate-despite-same-free-region.stderr | 6 +- ...ail-to-approximate-longer-no-bounds.stderr | 6 +- ...-to-approximate-longer-wrong-bounds.stderr | 6 +- .../propagate-from-trait-match.stderr | 9 +- ...n-lbr-named-does-not-outlive-static.stderr | 2 + .../region-lbr1-does-not-outlive-ebr2.stderr | 2 + .../return-wrong-bound-region.stderr | 6 +- .../constant-thread-locals-issue-47053.stderr | 1 + ...not-ignore-lifetime-bounds-in-copy-proj.rs | 12 + ...ignore-lifetime-bounds-in-copy-proj.stderr | 14 + .../ui/nll/generator-upvar-mutability.stderr | 1 + src/test/ui/nll/issue-16223.rs | 2 +- src/test/ui/nll/issue-21114-ebfull.rs | 2 +- src/test/ui/nll/issue-21114-kixunil.rs | 2 +- .../ui/nll/issue-22323-temp-destruction.rs | 2 +- src/test/ui/nll/issue-30104.rs | 2 +- ...ue-32382-index-assoc-type-with-lifetime.rs | 2 +- src/test/ui/nll/issue-43058.rs | 2 +- src/test/ui/nll/issue-47022.rs | 2 +- src/test/ui/nll/issue-47388.stderr | 1 + src/test/ui/nll/issue-50716-1.rs | 2 +- src/test/ui/nll/issue-50716.nll.stderr | 2 + src/test/ui/nll/issue-51244.stderr | 1 + src/test/ui/nll/issue-51351.rs | 2 +- src/test/ui/nll/issue-52078.rs | 2 +- src/test/ui/nll/issue-52113.stderr | 2 + src/test/ui/nll/issue-52534-2.stderr | 4 +- src/test/ui/nll/issue-53119.rs | 2 +- src/test/ui/nll/issue-53570.rs | 2 +- src/test/ui/nll/issue-55344.rs | 2 +- src/test/ui/nll/issue-55394.stderr | 10 +- src/test/ui/nll/issue-55401.nll.stderr | 2 + src/test/ui/nll/issue-55651.rs | 2 +- src/test/ui/nll/issue-57280-1.rs | 2 +- src/test/ui/nll/issue-57280.rs | 2 +- src/test/ui/nll/issue-57989.stderr | 3 +- src/test/ui/nll/issue-58299.stderr | 4 + src/test/ui/nll/issue-61311-normalize.rs | 2 +- src/test/ui/nll/issue-61320-normalize.rs | 2 +- src/test/ui/nll/issue-69114-static-mut-ty.rs | 30 + .../ui/nll/issue-69114-static-mut-ty.stderr | 27 + src/test/ui/nll/issue-69114-static-ty.rs | 9 + src/test/ui/nll/issue-69114-static-ty.stderr | 15 + src/test/ui/nll/mir_check_cast_closure.stderr | 2 + src/test/ui/nll/mir_check_cast_reify.stderr | 2 + .../ui/nll/mir_check_cast_unsafe_fn.stderr | 2 + src/test/ui/nll/mir_check_cast_unsize.stderr | 2 + src/test/ui/nll/move-errors.stderr | 14 +- .../ui/nll/normalization-bounds-error.stderr | 10 +- src/test/ui/nll/outlives-suggestion-more.rs | 28 + .../ui/nll/outlives-suggestion-more.stderr | 100 + ...outlives-suggestion-simple.polonius.stderr | 121 + src/test/ui/nll/outlives-suggestion-simple.rs | 77 + .../ui/nll/outlives-suggestion-simple.stderr | 108 + src/test/ui/nll/polonius/subset-relations.rs | 30 + .../ui/nll/polonius/subset-relations.stderr | 14 + src/test/ui/nll/relate_tys/issue-48071.rs | 2 +- .../ui/nll/trait-associated-constant.stderr | 4 +- src/test/ui/nll/ty-outlives/issue-53789-1.rs | 2 +- src/test/ui/nll/ty-outlives/issue-53789-2.rs | 2 +- src/test/ui/nll/ty-outlives/issue-55756.rs | 2 +- .../projection-no-regions-closure.stderr | 40 +- .../projection-one-region-closure.stderr | 48 +- ...tion-one-region-trait-bound-closure.stderr | 55 +- ...e-region-trait-bound-static-closure.stderr | 51 +- ...tion-two-region-trait-bound-closure.stderr | 96 +- ...ram-closure-approximate-lower-bound.stderr | 20 +- ...m-closure-outlives-from-return-type.stderr | 9 +- ...-closure-outlives-from-where-clause.stderr | 40 +- .../ui/nll/ty-outlives/wf-unreachable.stderr | 16 + .../ui/nll/type-alias-free-regions.stderr | 40 +- .../nll/type-check-pointer-coercions.stderr | 18 + .../nll/type-check-pointer-comparisons.stderr | 18 + .../closure-substs.polonius.stderr | 60 + .../user-annotations/closure-substs.stderr | 4 + .../constant-in-expr-inherent-1.nll.stderr | 2 + .../constant-in-expr-inherent-1.stderr | 10 +- .../constant-in-expr-normalize.nll.stderr | 2 + .../constant-in-expr-trait-item-1.nll.stderr | 2 + .../constant-in-expr-trait-item-2.nll.stderr | 2 + .../constant-in-expr-trait-item-3.nll.stderr | 2 + .../constant-in-expr-trait-item-3.stderr | 10 +- .../inherent-associated-constants.stderr | 2 + .../nll/user-annotations/issue-54124.stderr | 2 + .../issue-54570-bootstrapping.rs | 2 +- ...-55748-pat-types-constrain-bindings.stderr | 6 + .../issue-57731-ascibed-coupled-types.stderr | 8 + .../ui/nll/user-annotations/patterns.stderr | 8 + .../nll/user-annotations/wf-self-type.stderr | 2 + .../ui/nll/where_clauses_in_functions.stderr | 2 + .../ui/nll/where_clauses_in_structs.stderr | 2 + src/test/ui/no-send-res-ports.rs | 3 +- src/test/ui/no-send-res-ports.stderr | 6 +- .../no-warn-on-field-replace-issue-34101.rs | 2 +- src/test/ui/noexporttypeexe.rs | 4 +- src/test/ui/noexporttypeexe.stderr | 6 +- src/test/ui/non-integer-atomic.stderr | 1 + src/test/ui/numeric/const-scope.stderr | 20 +- src/test/ui/numeric/len.stderr | 2 +- src/test/ui/numeric/numeric-cast-2.stderr | 12 +- .../numeric-cast-without-suggestion.stderr | 42 +- src/test/ui/numeric/numeric-cast.stderr | 226 +- src/test/ui/numeric/numeric-suffix.stderr | 268 +- ...object-lifetime-default-elision.nll.stderr | 2 + .../object-lifetime-default-elision.stderr | 20 +- ...ime-default-from-rptr-box-error.nll.stderr | 2 + ...ifetime-default-from-rptr-box-error.stderr | 4 +- ...-default-from-rptr-struct-error.nll.stderr | 2 + ...time-default-from-rptr-struct-error.stderr | 4 +- .../object-lifetime-default-mybox.nll.stderr | 4 + .../object-lifetime-default-mybox.stderr | 7 +- .../ui/on-unimplemented/bad-annotation.rs | 2 +- .../ui/on-unimplemented/enclosing-scope.rs | 27 + .../on-unimplemented/enclosing-scope.stderr | 66 + .../expected-comma-found-token.rs | 4 +- .../expected-comma-found-token.stderr | 4 +- .../feature-gate-on-unimplemented.rs | 8 + .../feature-gate-on-unimplemented.stderr | 8 +- .../ui/on-unimplemented/multiple-impls.rs | 2 +- src/test/ui/on-unimplemented/on-impl.rs | 2 +- src/test/ui/on-unimplemented/on-trait.rs | 2 +- .../ui/once-cant-call-twice-on-heap.stderr | 4 +- .../ui/or-patterns/consistent-bindings.stderr | 5 +- .../exhaustiveness-non-exhaustive.rs | 26 + .../exhaustiveness-non-exhaustive.stderr | 33 + .../ui/or-patterns/exhaustiveness-pass.rs | 45 + .../ui/or-patterns/exhaustiveness-pass.stderr | 8 + .../exhaustiveness-unreachable-pattern.rs | 79 + .../exhaustiveness-unreachable-pattern.stderr | 110 + .../issue-64879-trailing-before-guard.stderr | 7 +- .../ui/or-patterns/or-pattern-mismatch.stderr | 5 +- .../or-patterns-syntactic-fail.stderr | 12 +- .../or-patterns/or-patterns-syntactic-pass.rs | 2 +- .../ui/order-dependent-cast-inference.stderr | 1 + src/test/ui/orphan-check-diagnostics.stderr | 1 + src/test/ui/output-type-mismatch.stderr | 5 +- src/test/ui/parser/assoc-oddities-1.stderr | 2 +- src/test/ui/parser/assoc-oddities-2.stderr | 2 +- ...ed-types-project-from-hrtb-explicit.stderr | 7 +- src/test/ui/parser/attr-bad-meta.stderr | 2 +- src/test/ui/parser/bad-lit-suffixes.rs | 4 +- src/test/ui/parser/bad-lit-suffixes.stderr | 4 +- src/test/ui/parser/bad-match.stderr | 2 +- src/test/ui/parser/bad-name.stderr | 2 +- src/test/ui/parser/better-expected.stderr | 2 +- src/test/ui/parser/bounds-lifetime-1.stderr | 2 +- src/test/ui/parser/bounds-lifetime-2.stderr | 2 +- .../ui/parser/bounds-lifetime-where.stderr | 2 +- src/test/ui/parser/bounds-lifetime.stderr | 2 +- src/test/ui/parser/bounds-type-where.stderr | 2 +- .../parser/class-implements-bad-trait.stderr | 2 +- .../ui/parser/closure-return-syntax.stderr | 2 +- src/test/ui/parser/default.stderr | 2 +- .../ui/parser/duplicate-visibility.stderr | 2 +- .../ui/parser/empty-impl-semicolon.stderr | 2 +- src/test/ui/parser/expr-as-stmt.stderr | 20 +- .../extern-abi-from-mac-literal-frag.rs | 26 + src/test/ui/parser/extern-abi-raw-strings.rs | 13 + .../ui/parser/extern-abi-string-escaping.rs | 13 + src/test/ui/parser/extern-abi-syntactic.rs | 17 + .../extern-crate-unexpected-token.stderr | 2 +- .../parser/extern-expected-fn-or-brace.stderr | 2 +- .../ui/parser/extern-foreign-crate.stderr | 2 +- src/test/ui/parser/fn-arg-doc-comment.rs | 9 +- src/test/ui/parser/fn-arg-doc-comment.stderr | 17 +- src/test/ui/parser/inverted-parameters.stderr | 12 +- src/test/ui/parser/issue-15980.rs | 2 +- src/test/ui/parser/issue-15980.stderr | 2 +- src/test/ui/parser/issue-17904.stderr | 2 +- src/test/ui/parser/issue-19096.stderr | 4 +- src/test/ui/parser/issue-20711-2.stderr | 2 +- src/test/ui/parser/issue-20711.stderr | 2 +- src/test/ui/parser/issue-22647.stderr | 2 +- src/test/ui/parser/issue-22712.stderr | 2 +- src/test/ui/parser/issue-24197.stderr | 2 +- src/test/ui/parser/issue-24375.stderr | 2 +- src/test/ui/parser/issue-24780.stderr | 2 +- src/test/ui/parser/issue-32446.stderr | 4 +- src/test/ui/parser/issue-33413.stderr | 5 +- src/test/ui/parser/issue-33455.stderr | 2 +- src/test/ui/parser/issue-41155.stderr | 2 +- ...ssue-58094-missing-right-square-bracket.rs | 4 + ...-58094-missing-right-square-bracket.stderr | 16 + src/test/ui/parser/issue-62524.rs | 4 + src/test/ui/parser/issue-62524.stderr | 34 + src/test/ui/parser/issue-62660.stderr | 2 +- src/test/ui/parser/issue-62881.stderr | 5 +- src/test/ui/parser/issue-62895.stderr | 5 +- src/test/ui/parser/issue-62973.stderr | 6 +- src/test/ui/parser/issue-63116.rs | 3 + src/test/ui/parser/issue-63116.stderr | 24 + src/test/ui/parser/issue-63135.stderr | 8 +- .../issue-65041-empty-vis-matcher-in-enum.rs | 28 + .../issue-65041-empty-vis-matcher-in-trait.rs | 28 + ...e-65846-rollback-gating-failing-matcher.rs | 14 + .../issue-66357-unexpected-unreachable.stderr | 2 +- .../ui/parser/lex-bad-char-literals-6.stderr | 7 +- .../ui/parser/lifetime-in-pattern-recover.rs | 6 + .../parser/lifetime-in-pattern-recover.stderr | 23 + src/test/ui/parser/lifetime-in-pattern.rs | 1 + src/test/ui/parser/lifetime-in-pattern.stderr | 10 +- src/test/ui/parser/lifetime-semicolon.stderr | 2 +- .../ui/parser/macro-bad-delimiter-ident.rs | 2 +- .../parser/macro-bad-delimiter-ident.stderr | 4 +- src/test/ui/parser/macro/issue-37234.stderr | 2 +- .../parser/macro/macro-doc-comments-2.stderr | 2 +- .../macro/macro-incomplete-parse.stderr | 2 +- .../ui/parser/macro/trait-non-item-macros.rs | 2 +- .../parser/macro/trait-non-item-macros.stderr | 4 +- .../parser/macros-no-semicolon-items.stderr | 6 +- src/test/ui/parser/macros-no-semicolon.stderr | 2 +- src/test/ui/parser/match-refactor-to-expr.rs | 2 +- .../ui/parser/match-refactor-to-expr.stderr | 2 +- src/test/ui/parser/match-vec-invalid.stderr | 5 +- src/test/ui/parser/mbe_missing_right_paren.rs | 3 + .../ui/parser/mbe_missing_right_paren.stderr | 31 + .../missing-close-brace-in-impl-trait.stderr | 2 +- .../missing-close-brace-in-struct.stderr | 5 - .../missing-close-brace-in-trait.rs | 4 +- .../missing-close-brace-in-trait.stderr | 31 +- src/test/ui/parser/missing_right_paren.rs | 3 + src/test/ui/parser/missing_right_paren.stderr | 17 + src/test/ui/parser/multitrait.stderr | 2 +- src/test/ui/parser/not-a-pred.stderr | 2 +- src/test/ui/parser/numeric-lifetime.stderr | 7 +- .../ui/parser/omitted-arg-in-item-fn.stderr | 2 +- src/test/ui/parser/pat-lt-bracket-1.stderr | 2 +- src/test/ui/parser/pat-lt-bracket-2.stderr | 2 +- src/test/ui/parser/pat-lt-bracket-3.stderr | 2 +- src/test/ui/parser/pat-lt-bracket-4.stderr | 2 +- src/test/ui/parser/pat-lt-bracket-5.stderr | 2 +- src/test/ui/parser/pat-lt-bracket-6.stderr | 10 +- src/test/ui/parser/pat-lt-bracket-7.stderr | 10 +- src/test/ui/parser/pat-ranges-1.stderr | 2 +- src/test/ui/parser/pat-ranges-2.stderr | 2 +- src/test/ui/parser/pat-ranges-3.stderr | 2 +- src/test/ui/parser/pat-ranges-4.stderr | 2 +- src/test/ui/parser/pat-tuple-4.stderr | 5 +- src/test/ui/parser/pat-tuple-5.stderr | 6 +- src/test/ui/parser/range-3.stderr | 2 +- src/test/ui/parser/range-4.stderr | 2 +- src/test/ui/parser/raw-str-unbalanced.stderr | 2 +- .../ui/parser/raw/raw-literal-keywords.rs | 4 +- .../ui/parser/raw/raw-literal-keywords.stderr | 10 +- src/test/ui/parser/recover-enum.rs | 12 +- src/test/ui/parser/recover-enum.stderr | 35 +- src/test/ui/parser/recover-enum2.stderr | 2 +- ...recover-for-loop-parens-around-head.stderr | 7 +- .../ui/parser/recover-from-homoglyph.stderr | 7 +- .../ui/parser/recover-missing-semi.stderr | 14 +- src/test/ui/parser/recover-range-pats.stderr | 108 +- src/test/ui/parser/recover-tuple.stderr | 7 +- .../removed-syntax-closure-lifetime.stderr | 2 +- .../parser/removed-syntax-enum-newtype.stderr | 2 +- .../ui/parser/removed-syntax-field-let.stderr | 5 - .../ui/parser/removed-syntax-fixed-vec.stderr | 2 +- .../parser/removed-syntax-ptr-lifetime.stderr | 2 +- .../ui/parser/removed-syntax-static-fn.stderr | 2 +- .../parser/removed-syntax-uniq-mut-ty.stderr | 2 +- .../ui/parser/removed-syntax-with-1.stderr | 2 +- .../ui/parser/removed-syntax-with-2.stderr | 2 +- ...quire-parens-for-chained-comparison.stderr | 10 +- ...truct-literal-restrictions-in-lamda.stderr | 4 +- .../ui/parser/trait-pub-assoc-const.stderr | 5 +- src/test/ui/parser/trait-pub-assoc-ty.stderr | 5 +- src/test/ui/parser/trait-pub-method.stderr | 5 +- .../parser/unclosed-delimiter-in-dep.stderr | 6 +- .../parser/underscore_item_not_const.stderr | 2 +- .../use-as-where-use-ends-with-mod-sep.stderr | 7 +- src/test/ui/path-lookahead.rs | 8 +- src/test/ui/path-lookahead.stderr | 24 +- src/test/ui/pathless-extern-ok.rs | 9 + .../issue-53820-slice-pattern-large-array.rs | 13 + src/test/ui/pattern/pat-tuple-bad-type.stderr | 5 +- .../ui/pattern/pat-tuple-overfield.stderr | 8 +- .../pattern/patkind-litrange-no-expr.stderr | 8 +- src/test/ui/pattern/pattern-error-continue.rs | 6 +- .../ui/pattern/pattern-error-continue.stderr | 11 +- .../pattern-ident-path-generics.stderr | 6 +- src/test/ui/pattern/pattern-tyvar.stderr | 6 +- ...413-constants-and-slices-exhaustiveness.rs | 15 + .../always-inhabited-union-ref.stderr | 9 +- .../usefulness/exhaustive_integer_patterns.rs | 15 + .../exhaustive_integer_patterns.stderr | 8 +- .../match-byte-array-patterns-2.stderr | 8 +- .../match-empty-exhaustive_patterns.rs | 93 + .../match-empty-exhaustive_patterns.stderr | 223 + src/test/ui/pattern/usefulness/match-empty.rs | 92 + .../ui/pattern/usefulness/match-empty.stderr | 204 + .../usefulness/match-slice-patterns.rs | 2 +- .../usefulness/match-slice-patterns.stderr | 4 +- .../usefulness/non-exhaustive-match.rs | 2 +- .../usefulness/non-exhaustive-match.stderr | 4 +- .../{ => usefulness}/slice-pattern-const-2.rs | 0 .../slice-pattern-const-2.stderr | 0 .../{ => usefulness}/slice-pattern-const-3.rs | 0 .../slice-pattern-const-3.stderr | 0 .../{ => usefulness}/slice-pattern-const.rs | 7 + .../slice-pattern-const.stderr | 8 +- .../slice-patterns-exhaustiveness.rs | 107 + .../slice-patterns-exhaustiveness.stderr | 131 + .../usefulness/slice-patterns-irrefutable.rs | 27 + .../usefulness/slice-patterns-reachability.rs | 26 + .../slice-patterns-reachability.stderr | 44 + .../usefulness/top-level-alternation.rs | 56 + .../usefulness/top-level-alternation.stderr | 68 + ...pe-err-cause-on-impl-trait-return-2.stderr | 6 +- ...type-err-cause-on-impl-trait-return.stderr | 35 +- src/test/ui/pptypedef.rs | 4 +- src/test/ui/pptypedef.stderr | 4 +- .../ui/print_type_sizes/zero-sized-fields.rs | 46 + .../print_type_sizes/zero-sized-fields.stdout | 16 + src/test/ui/privacy/issue-57264-1.rs | 2 +- src/test/ui/privacy/issue-57264-2.rs | 2 +- src/test/ui/privacy/legacy-ctor-visibility.rs | 7 +- .../ui/privacy/legacy-ctor-visibility.stderr | 17 +- src/test/ui/privacy/privacy-ns1.rs | 3 +- src/test/ui/privacy/privacy-ns1.stderr | 44 +- src/test/ui/privacy/privacy-ns2.rs | 6 +- src/test/ui/privacy/privacy-ns2.stderr | 75 +- src/test/ui/privacy/pub-priv-dep/pub-priv1.rs | 5 +- .../ui/privacy/pub-priv-dep/pub-priv1.stderr | 8 +- .../attribute-spans-preserved.stderr | 14 +- .../ui/proc-macro/attribute-with-error.stderr | 28 +- src/test/ui/proc-macro/attribute.stderr | 24 +- .../auxiliary/derive-helper-shadowing-2.rs | 12 + .../auxiliary/derive-helper-shadowing.rs | 15 + .../proc-macro/derive-helper-shadowing-2.rs | 16 + .../ui/proc-macro/derive-helper-shadowing.rs | 35 +- .../proc-macro/derive-helper-shadowing.stderr | 53 +- .../ui/proc-macro/dollar-crate-issue-57089.rs | 2 +- .../ui/proc-macro/expand-to-unstable-2.rs | 4 +- .../ui/proc-macro/expand-to-unstable-2.stderr | 2 +- src/test/ui/proc-macro/exports.stderr | 8 +- src/test/ui/proc-macro/issue-37788.stderr | 6 +- src/test/ui/proc-macro/issue-41211.rs | 6 +- src/test/ui/proc-macro/issue-41211.stderr | 19 +- src/test/ui/proc-macro/macro-brackets.stderr | 2 +- .../ui/proc-macro/nested-item-spans.stderr | 14 +- src/test/ui/proc-macro/no-macro-use-attr.rs | 2 +- .../ui/proc-macro/no-macro-use-attr.stderr | 2 +- src/test/ui/proc-macro/proc-macro-gates.rs | 2 +- .../ui/proc-macro/proc-macro-gates.stderr | 2 +- src/test/ui/proc-macro/pub-at-crate-root.rs | 2 +- .../ui/proc-macro/pub-at-crate-root.stderr | 2 +- src/test/ui/proc-macro/signature.stderr | 4 +- src/test/ui/proc-macro/span-preservation.rs | 20 +- .../ui/proc-macro/span-preservation.stderr | 60 +- src/test/ui/ptr-coercion.rs | 12 +- src/test/ui/ptr-coercion.stderr | 24 +- .../ui/qualified/qualified-path-params.stderr | 7 +- src/test/ui/question-mark-type-infer.rs | 2 +- src/test/ui/question-mark-type-infer.stderr | 11 +- .../ui/range/issue-54505-no-literals.stderr | 48 +- src/test/ui/range/issue-54505-no-std.stderr | 24 +- src/test/ui/range/issue-54505.stderr | 24 +- src/test/ui/range/range-1.stderr | 2 +- src/test/ui/raw-ref-op/feature-raw-ref-op.rs | 21 + .../ui/raw-ref-op/feature-raw-ref-op.stderr | 57 + src/test/ui/raw-ref-op/raw-ref-op.rs | 13 + src/test/ui/raw-ref-op/raw-ref-op.stderr | 18 + src/test/ui/raw-ref-op/raw-ref-temp-deref.rs | 24 + .../ui/raw-ref-op/raw-ref-temp-deref.stderr | 74 + src/test/ui/raw-ref-op/raw-ref-temp.rs | 29 + src/test/ui/raw-ref-op/raw-ref-temp.stderr | 99 + src/test/ui/raw-ref-op/unusual_locations.rs | 25 + .../ui/raw-ref-op/unusual_locations.stderr | 18 + .../ui/reachable/unreachable-loop-patterns.rs | 2 +- ...ons-fn-subtyping-return-static-fail.stderr | 8 +- ...6537-closure-uses-region-from-container.rs | 2 +- ...nvariant-static-error-reporting.nll.stderr | 2 + ...on-invariant-static-error-reporting.stderr | 4 +- ...time-bounds-on-fns-where-clause.nll.stderr | 8 +- ...lifetime-bounds-on-fns-where-clause.stderr | 11 +- ...time-bounds-on-fns-where-clause.nll.stderr | 8 +- ...lifetime-bounds-on-fns-where-clause.stderr | 11 +- .../region-object-lifetime-2.nll.stderr | 2 + .../region-object-lifetime-4.nll.stderr | 2 + ...ion-object-lifetime-in-coercion.nll.stderr | 2 + .../region-object-lifetime-in-coercion.stderr | 20 +- .../regions/regions-addr-of-upvar-self.stderr | 2 +- ...rait-outlives-container.migrate.nll.stderr | 2 + ...n-supertrait-outlives-container.nll.stderr | 2 + ...-type-region-bound-in-trait-not-met.stderr | 20 +- ...-type-static-bound-in-trait-not-met.stderr | 10 +- ...unded-by-trait-requiring-static.nll.stderr | 12 + ...hod-type-parameters-cross-crate.nll.stderr | 2 + ...-method-type-parameters-cross-crate.stderr | 1 + ...hod-type-parameters-trait-bound.nll.stderr | 2 + ...-method-type-parameters-trait-bound.stderr | 1 + ...-bounded-method-type-parameters.nll.stderr | 2 + src/test/ui/regions/regions-bounds.nll.stderr | 4 + src/test/ui/regions/regions-bounds.stderr | 8 +- ...ions-close-object-into-object-2.nll.stderr | 2 + .../regions-close-object-into-object-2.stderr | 10 +- ...ions-close-object-into-object-4.nll.stderr | 2 + .../regions-close-object-into-object-4.stderr | 10 +- ...se-over-type-parameter-multiple.nll.stderr | 2 + ...-close-over-type-parameter-multiple.stderr | 10 +- .../regions-creating-enums3.nll.stderr | 2 + .../ui/regions/regions-creating-enums3.stderr | 1 + .../regions-creating-enums4.nll.stderr | 2 + .../ui/regions/regions-creating-enums4.stderr | 20 +- ...egions-early-bound-error-method.nll.stderr | 2 + .../regions-early-bound-error.nll.stderr | 2 + .../ui/regions/regions-escape-method.stderr | 10 +- .../regions-escape-via-trait-or-not.stderr | 10 +- .../regions-fn-subtyping-return-static.stderr | 4 +- ...ons-free-region-ordering-callee.nll.stderr | 4 + ...regions-free-region-ordering-callee.stderr | 1 + ...-region-ordering-caller.migrate.nll.stderr | 6 + ...free-region-ordering-caller.migrate.stderr | 1 + ...ons-free-region-ordering-caller.nll.stderr | 6 + ...-free-region-ordering-incorrect.nll.stderr | 2 + ...nfer-contravariance-due-to-decl.nll.stderr | 2 + ...ns-infer-contravariance-due-to-decl.stderr | 1 + ...ns-infer-covariance-due-to-decl.nll.stderr | 2 + ...egions-infer-covariance-due-to-decl.stderr | 1 + ...ns-infer-invariance-due-to-decl.nll.stderr | 2 + ...egions-infer-invariance-due-to-decl.stderr | 4 +- ...-invariance-due-to-mutability-3.nll.stderr | 2 + ...nfer-invariance-due-to-mutability-3.stderr | 4 +- ...-invariance-due-to-mutability-4.nll.stderr | 2 + ...nfer-invariance-due-to-mutability-4.stderr | 4 +- .../regions-infer-not-param.nll.stderr | 8 + .../ui/regions/regions-infer-not-param.rs | 8 +- .../ui/regions/regions-infer-not-param.stderr | 12 +- .../regions/regions-infer-paramd-indirect.rs | 4 +- .../regions-infer-paramd-indirect.stderr | 4 +- .../regions-lifetime-bounds-on-fns.nll.stderr | 8 +- .../regions-lifetime-bounds-on-fns.stderr | 11 +- .../ui/regions/regions-nested-fns.nll.stderr | 2 + src/test/ui/regions/regions-nested-fns.stderr | 15 +- ...ions-normalize-in-where-clause-list.stderr | 13 +- ...ojection-container-hrtb.migrate.nll.stderr | 4 + ...lives-projection-container-hrtb.nll.stderr | 4 + ...projection-container-wc.migrate.nll.stderr | 2 + ...utlives-projection-container-wc.nll.stderr | 2 + ...s-outlives-projection-container.nll.stderr | 8 + ...ow-from-shorter-mut-ref-mut-ref.nll.stderr | 2 + ...borrow-from-shorter-mut-ref-mut-ref.stderr | 1 + ...s-reborrow-from-shorter-mut-ref.nll.stderr | 2 + ...gions-reborrow-from-shorter-mut-ref.stderr | 1 + .../ui/regions/regions-ret-borrowed-1.stderr | 10 +- .../ui/regions/regions-ret-borrowed.stderr | 10 +- .../regions-static-bound.migrate.nll.stderr | 2 + .../regions/regions-static-bound.nll.stderr | 2 + src/test/ui/regions/regions-trait-1.stderr | 4 +- .../regions-trait-object-subtyping.nll.stderr | 4 + .../regions-trait-object-subtyping.stderr | 14 +- ...se-covariant-in-second-position.nll.stderr | 2 + ...nt-use-covariant-in-second-position.stderr | 1 + ...nce-contravariant-use-covariant.nll.stderr | 2 + ...ariance-contravariant-use-covariant.stderr | 1 + ...nce-covariant-use-contravariant.nll.stderr | 2 + ...ariance-covariant-use-contravariant.stderr | 1 + ...nce-invariant-use-contravariant.nll.stderr | 2 + ...ariance-invariant-use-contravariant.stderr | 1 + ...ariance-invariant-use-covariant.nll.stderr | 2 + ...ns-variance-invariant-use-covariant.stderr | 4 +- src/test/ui/reify-intrinsic.stderr | 13 +- src/test/ui/reject-specialized-drops-8142.rs | 4 +- .../ui/reject-specialized-drops-8142.stderr | 14 +- src/test/ui/removing-extern-crate.fixed | 11 +- src/test/ui/removing-extern-crate.rs | 11 +- src/test/ui/removing-extern-crate.stderr | 8 +- src/test/ui/repeat_count.rs | 22 +- src/test/ui/repeat_count.stderr | 38 +- src/test/ui/repr.stderr | 6 +- src/test/ui/resolve/issue-57523.rs | 2 +- src/test/ui/resolve/name-clash-nullary.stderr | 4 +- src/test/ui/resolve/privacy-enum-ctor.stderr | 45 +- .../resolve-inconsistent-binding-mode.stderr | 10 +- .../resolve/resolve-inconsistent-names.stderr | 5 +- .../ui/resolve/token-error-correct-3.stderr | 2 +- src/test/ui/retslot-cast.stderr | 4 +- .../ui/return/return-from-diverging.stderr | 6 +- .../ui/return/return-match-array-const.rs | 12 +- .../ui/return/return-match-array-const.stderr | 36 +- src/test/ui/return/return-type.stderr | 6 +- .../termination-trait-test-wrong-type.rs | 3 +- .../termination-trait-test-wrong-type.stderr | 2 +- .../const.stderr | 5 +- .../rfc-2005-default-binding-mode/enum.stderr | 1 + .../explicit-mut.stderr | 1 + .../rfc-2005-default-binding-mode/lit.stderr | 12 +- .../auxiliary/enums.rs | 3 + src/test/ui/rfc-2008-non-exhaustive/enum.rs | 12 +- .../ui/rfc-2008-non-exhaustive/enum.stderr | 20 +- .../enum_same_crate_empty_match.rs | 37 + .../enum_same_crate_empty_match.stderr | 45 + .../uninhabited/coercions.stderr | 12 - .../uninhabited/coercions_same_crate.stderr | 12 - .../uninhabited/indirect_match.stderr | 8 +- .../indirect_match_same_crate.stderr | 28 +- .../uninhabited/match.stderr | 8 +- .../uninhabited/match_same_crate.stderr | 22 +- .../match_with_exhaustive_patterns.stderr | 4 +- .../manual-self-impl-for-unsafe-obj.rs | 15 +- .../caller-location-intrinsic.rs | 24 +- .../const-caller-location.rs | 41 + .../rfc-2091-track-caller/error-odd-syntax.rs | 2 +- .../error-odd-syntax.stderr | 8 - .../error-with-invalid-abi.rs | 5 +- .../error-with-invalid-abi.stderr | 10 +- .../rfc-2091-track-caller/error-with-naked.rs | 2 +- .../error-with-naked.stderr | 8 - .../error-with-trait-decl.rs | 2 +- .../error-with-trait-decl.stderr | 8 - .../error-with-trait-default-impl.rs | 2 +- .../error-with-trait-default-impl.stderr | 8 - .../error-with-trait-fn-impl.rs | 2 +- .../error-with-trait-fn-impl.stderr | 8 - .../intrinsic-wrapper.rs | 21 + .../ui/rfc-2091-track-caller/only-for-fns.rs | 2 +- .../rfc-2091-track-caller/only-for-fns.stderr | 8 - src/test/ui/rfc-2091-track-caller/pass.rs | 2 +- src/test/ui/rfc-2091-track-caller/pass.stderr | 8 - .../track-caller-attribute.rs | 40 + .../ui/rfc-2093-infer-outlives/issue-54467.rs | 2 +- .../disallowed-positions.rs | 9 +- .../disallowed-positions.stderr | 251 +- .../protect-precedences.rs | 2 +- .../param-attrs-2018.stderr | 2 +- src/test/ui/rfc1445/feature-gate.rs | 2 +- .../ui/rfc1445/feature-gate.with_gate.stderr | 2 +- .../empty_generics.stderr | 2 +- .../ui/rust-2018/remove-extern-crate.fixed | 4 +- src/test/ui/rust-2018/remove-extern-crate.rs | 4 +- src/test/ui/rust-2018/try-ident.fixed | 4 + src/test/ui/rust-2018/try-ident.rs | 4 + src/test/ui/rust-2018/try-ident.stderr | 2 +- src/test/ui/rust-2018/try-macro.fixed | 5 +- src/test/ui/rust-2018/try-macro.rs | 5 +- src/test/ui/rust-2018/try-macro.stderr | 2 +- .../rust-2018/uniform-paths/issue-56596-2.rs | 2 +- src/test/ui/rustc-error.rs | 2 +- src/test/ui/rustc-error.stderr | 2 +- src/test/ui/safe-extern-statics.rs | 6 - src/test/ui/safe-extern-statics.stderr | 34 +- src/test/ui/sanitize-cfg.rs | 26 + ...ary-self-types-not-object-safe.curr.stderr | 4 +- ...bject-safe.object_safe_for_dispatch.stderr | 2 +- .../arbitrary-self-types-not-object-safe.rs | 1 - ...rbitrary-self-types-not-object-safe.stderr | 4 +- .../ui/self/arbitrary_self_types_nested.rs | 36 + ...s_pin_lifetime_impl_trait-async.nll.stderr | 6 +- ...types_pin_lifetime_impl_trait-async.stderr | 4 - ...pes_pin_lifetime_mismatch-async.nll.stderr | 21 +- ...f_types_pin_lifetime_mismatch-async.stderr | 1 + ...ry_self_types_pin_lifetime_mismatch.stderr | 1 + .../ui/self/arbitrary_self_types_struct.rs | 1 - .../ui/self/arbitrary_self_types_trait.rs | 1 - .../arbitrary_self_types_unsized_struct.rs | 1 - src/test/ui/self/elision/alias-async.rs | 1 - src/test/ui/self/elision/alias.rs | 1 - src/test/ui/self/elision/assoc-async.rs | 1 - src/test/ui/self/elision/assoc.rs | 1 - src/test/ui/self/elision/lt-alias-async.rs | 1 - src/test/ui/self/elision/lt-alias.rs | 1 - src/test/ui/self/elision/lt-assoc-async.rs | 1 - src/test/ui/self/elision/lt-assoc.rs | 1 - .../self/elision/lt-ref-self-async.nll.stderr | 66 +- src/test/ui/self/elision/lt-ref-self-async.rs | 1 - .../ui/self/elision/lt-ref-self-async.stderr | 13 +- .../ui/self/elision/lt-ref-self.nll.stderr | 12 +- src/test/ui/self/elision/lt-ref-self.rs | 1 - src/test/ui/self/elision/lt-ref-self.stderr | 13 +- src/test/ui/self/elision/lt-self-async.rs | 1 - src/test/ui/self/elision/lt-self.rs | 1 - src/test/ui/self/elision/lt-struct-async.rs | 1 - src/test/ui/self/elision/lt-struct.rs | 1 - src/test/ui/self/elision/ref-alias-async.rs | 1 - src/test/ui/self/elision/ref-alias.rs | 1 - src/test/ui/self/elision/ref-assoc-async.rs | 1 - src/test/ui/self/elision/ref-assoc.rs | 1 - .../ui/self/elision/ref-mut-alias-async.rs | 1 - src/test/ui/self/elision/ref-mut-alias.rs | 1 - .../elision/ref-mut-self-async.nll.stderr | 66 +- .../ui/self/elision/ref-mut-self-async.rs | 1 - .../ui/self/elision/ref-mut-self-async.stderr | 13 +- .../ui/self/elision/ref-mut-self.nll.stderr | 12 +- src/test/ui/self/elision/ref-mut-self.rs | 1 - src/test/ui/self/elision/ref-mut-self.stderr | 13 +- .../elision/ref-mut-struct-async.nll.stderr | 55 +- .../ui/self/elision/ref-mut-struct-async.rs | 1 - .../self/elision/ref-mut-struct-async.stderr | 11 +- .../ui/self/elision/ref-mut-struct.nll.stderr | 10 +- src/test/ui/self/elision/ref-mut-struct.rs | 1 - .../ui/self/elision/ref-mut-struct.stderr | 11 +- .../ui/self/elision/ref-self-async.nll.stderr | 139 +- src/test/ui/self/elision/ref-self-async.rs | 1 - .../ui/self/elision/ref-self-async.stderr | 15 +- src/test/ui/self/elision/ref-self.stderr | 1 + .../self/elision/ref-struct-async.nll.stderr | 55 +- src/test/ui/self/elision/ref-struct-async.rs | 1 - .../ui/self/elision/ref-struct-async.stderr | 11 +- .../ui/self/elision/ref-struct.nll.stderr | 10 +- src/test/ui/self/elision/ref-struct.rs | 1 - src/test/ui/self/elision/ref-struct.stderr | 11 +- src/test/ui/self/elision/self-async.rs | 1 - src/test/ui/self/elision/self.rs | 1 - src/test/ui/self/elision/struct-async.rs | 1 - src/test/ui/self/elision/struct.rs | 1 - .../ui/self/self-vs-path-ambiguity.stderr | 2 +- src/test/ui/shift-various-bad-types.rs | 2 +- src/test/ui/shift-various-bad-types.stderr | 4 +- ...insic-generic-arithmetic-saturating.stderr | 1 + .../simd-intrinsic-generic-arithmetic.stderr | 1 + .../simd-intrinsic-generic-bitmask.stderr | 1 + .../simd-intrinsic-generic-cast.stderr | 1 + .../simd-intrinsic-generic-comparison.stderr | 1 + .../simd-intrinsic-generic-elements.stderr | 1 + .../simd-intrinsic-generic-reduction.stderr | 1 + .../simd-intrinsic-generic-select.stderr | 1 + .../ui/simd/simd-intrinsic-float-minmax.rs | 1 - src/test/ui/similar-tokens.stderr | 5 +- src/test/ui/slice-mut.rs | 4 +- src/test/ui/slice-mut.stderr | 8 +- .../slightly-nice-generic-literal-messages.rs | 2 +- ...ghtly-nice-generic-literal-messages.stderr | 4 +- src/test/ui/span/coerce-suggestions.stderr | 31 +- .../ui/span/impl-wrong-item-for-trait.stderr | 2 +- src/test/ui/span/issue-23729.stderr | 2 +- src/test/ui/span/issue-23827.stderr | 2 +- src/test/ui/span/issue-24356.stderr | 2 +- src/test/ui/span/issue-24690.rs | 2 +- src/test/ui/span/issue-33884.stderr | 2 - src/test/ui/span/issue-34264.stderr | 11 +- src/test/ui/span/issue-36530.rs | 4 +- src/test/ui/span/issue-36530.stderr | 2 +- src/test/ui/span/issue-36537.stderr | 4 +- src/test/ui/span/issue-39018.stderr | 5 +- .../span/issue-42234-unknown-receiver-type.rs | 4 +- .../issue-42234-unknown-receiver-type.stderr | 9 +- src/test/ui/span/macro-ty-params.rs | 1 - src/test/ui/span/macro-ty-params.stderr | 8 +- src/test/ui/span/move-closure.stderr | 8 +- .../span/type-annotations-needed-expr.stderr | 5 +- ... => unused-warning-point-at-identifier.rs} | 4 +- ...unused-warning-point-at-identifier.stderr} | 25 +- .../specialization-default-projection.stderr | 12 +- .../specialization-default-types.stderr | 8 +- .../stability-attribute-sanity.rs | 7 +- .../stability-attribute-sanity.stderr | 10 +- .../ui/static/static-mut-bad-types.stderr | 2 +- .../ui/static/static-reference-to-fn-1.stderr | 4 +- src/test/ui/str/str-array-assignment.stderr | 22 +- src/test/ui/str/str-lit-type-mismatch.stderr | 39 +- .../ui/struct-literal-variant-in-if.stderr | 12 +- .../ui/structs/struct-base-wrong-type.stderr | 12 - .../struct-path-self-type-mismatch.stderr | 25 +- src/test/ui/structs/struct-path-self.stderr | 6 +- .../structure-constructor-type-mismatch.rs | 12 +- ...structure-constructor-type-mismatch.stderr | 58 +- src/test/ui/substs-ppaux.normal.stderr | 52 +- src/test/ui/substs-ppaux.rs | 32 +- src/test/ui/substs-ppaux.verbose.stderr | 52 +- src/test/ui/suggestions/as-ref.stderr | 49 +- ...as-arg-where-it-should-have-been-called.rs | 3 + ...rg-where-it-should-have-been-called.stderr | 21 +- ...gest-deref-inside-macro-issue-58298.stderr | 4 +- .../duplicate-suggestions.stderr | 108 +- .../dont-suggest-ref/simple.stderr | 17 +- .../dont-suggest-try_into-in-macros.stderr | 2 +- ...as-arg-where-it-should-have-been-called.rs | 2 + ...rg-where-it-should-have-been-called.stderr | 19 +- .../fn-or-tuple-struct-without-args.stderr | 160 +- src/test/ui/suggestions/format-borrow.stderr | 24 +- src/test/ui/suggestions/issue-52820.stderr | 10 +- src/test/ui/suggestions/issue-57672.rs | 2 +- src/test/ui/suggestions/issue-59819.stderr | 36 +- src/test/ui/suggestions/issue-62843.stderr | 8 +- .../suggestions/issue-64252-self-type.stderr | 4 +- .../let-binding-init-expr-as-ty.rs | 2 +- .../let-binding-init-expr-as-ty.stderr | 19 +- .../ui/suggestions/match-ergonomics.stderr | 18 +- .../ui/suggestions/match-needing-semi.stderr | 10 +- .../mismatched-types-numeric-from.stderr | 4 +- .../ui/suggestions/missing-trait-item.fixed | 20 + src/test/ui/suggestions/missing-trait-item.rs | 16 + .../ui/suggestions/missing-trait-item.stderr | 25 + .../suggestions/mut-ref-reassignment.stderr | 16 +- .../ui/suggestions/opaque-type-error.stderr | 4 +- .../ui/suggestions/option-content-move2.rs | 16 + .../suggestions/option-content-move2.stderr | 18 + .../ui/suggestions/raw-name-use-suggestion.rs | 9 + .../raw-name-use-suggestion.stderr | 36 + ...ecover-from-semicolon-trailing-item.stderr | 19 +- src/test/ui/suggestions/suggest-box.stderr | 8 +- .../ui/suggestions/suggest-ref-mut.stderr | 1 + .../type-ascription-instead-of-path-2.rs | 5 + .../type-ascription-instead-of-path-2.stderr | 13 + ...e-mismatch-struct-field-shorthand-2.stderr | 4 +- ...ype-mismatch-struct-field-shorthand.stderr | 6 +- src/test/ui/suppressed-error.rs | 6 +- src/test/ui/suppressed-error.stderr | 6 +- src/test/ui/switched-expectations.stderr | 5 +- src/test/ui/symbol-names/impl1.legacy.stderr | 4 +- .../ui/tag-that-dare-not-speak-its-name.rs | 4 +- .../tag-that-dare-not-speak-its-name.stderr | 6 +- src/test/ui/tail-typeck.stderr | 7 +- src/test/ui/target-feature/gate.rs | 1 - src/test/ui/target-feature/gate.stderr | 2 +- .../non-1-width-unicode-multiline-label.rs | 7 + ...non-1-width-unicode-multiline-label.stderr | 17 + .../non-whitespace-trimming-2.stderr | 9 +- .../non-whitespace-trimming-unicode.stderr | 9 +- .../non-whitespace-trimming.stderr | 9 +- .../whitespace-trimming-2.stderr | 5 +- .../terminal-width/whitespace-trimming.stderr | 7 +- src/test/ui/terr-in-field.rs | 2 - src/test/ui/terr-in-field.stderr | 3 - src/test/ui/terr-sorts.rs | 4 +- src/test/ui/terr-sorts.stderr | 4 +- src/test/ui/test-attrs/test-on-macro.rs | 4 +- .../ui/test-attrs/test-warns-dead-code.stderr | 4 +- src/test/ui/test-panic-abort-disabled.rs | 2 +- src/test/ui/test-panic-abort-disabled.stderr | 2 +- src/test/ui/thread-local-in-ctfe.rs | 2 - src/test/ui/thread-local-in-ctfe.stderr | 31 +- src/test/ui/thread-local-mutation.stderr | 1 + src/test/ui/thread-local-not-in-prelude.rs | 1 - src/test/ui/traits/auxiliary/crate_a1.rs | 12 +- src/test/ui/traits/auxiliary/crate_a2.rs | 13 + .../ui/traits/cycle-cache-err-60010.stderr | 4 +- .../ui/traits/principal-less-trait-objects.rs | 4 +- .../ui/traits/trait-bounds-same-crate-name.rs | 55 + .../trait-bounds-same-crate-name.stderr | 64 + src/test/ui/traits/trait-bounds-sugar.stderr | 4 +- .../ui/traits/trait-impl-method-mismatch.rs | 4 +- .../traits/trait-impl-method-mismatch.stderr | 4 +- ...trait-has-wrong-lifetime-parameters.stderr | 10 +- .../ui/traits/trait-matching-lifetimes.stderr | 8 +- ...n-projection-output-repeated-supertrait.rs | 2 +- ...ait-static-method-generic-inference.stderr | 6 +- .../ui/traits/trait-suggest-where-clause.rs | 3 +- .../traits/trait-suggest-where-clause.stderr | 14 +- ...traits-assoc-type-in-supertrait-bad.stderr | 5 +- .../ui/traits/traits-issue-23003-overflow.rs | 2 +- .../ui/traits/traits-multidispatch-bad.stderr | 2 +- ...ts-multidispatch-convert-ambig-dest.stderr | 2 +- .../ui/traits/traits-negative-impls.stderr | 14 +- .../trivial-bounds-inconsistent-copy.rs | 10 +- .../trivial-bounds-inconsistent-copy.stderr | 8 +- ...ounds-inconsistent-projection-error.stderr | 2 +- .../trivial-bounds-inconsistent-projection.rs | 10 +- ...vial-bounds-inconsistent-projection.stderr | 4 +- .../trivial-bounds-inconsistent-sized.rs | 3 + .../trivial-bounds-inconsistent-sized.stderr | 4 +- ...trivial-bounds-inconsistent-well-formed.rs | 2 + .../trivial-bounds-inconsistent.rs | 25 +- .../trivial-bounds-inconsistent.stderr | 16 +- .../ui/try-block/try-block-bad-type.stderr | 10 +- .../try-block/try-block-in-edition2015.stderr | 5 - .../ui/try-block/try-block-type-error.stderr | 10 +- .../try-block-unreachable-code-lint.rs | 6 +- src/test/ui/try-on-option-diagnostics.stderr | 19 +- src/test/ui/try-on-option.stderr | 9 +- src/test/ui/try-operator-on-main.stderr | 11 +- src/test/ui/tuple/tuple-arity-mismatch.rs | 8 +- src/test/ui/tuple/tuple-arity-mismatch.stderr | 8 +- .../ui/tuple/tuple-struct-fields/test.stderr | 4 +- .../ui/tuple/tuple-struct-fields/test2.stderr | 4 +- .../ui/tuple/tuple-struct-fields/test3.stderr | 4 +- src/test/ui/tutorial-suffix-inference-test.rs | 6 +- .../ui/tutorial-suffix-inference-test.stderr | 6 +- .../enum-variant-generic-args.stderr | 54 +- ...priority-higher-than-other-inherent.stderr | 7 +- .../type-alias-enum-variants/issue-57866.rs | 2 +- .../issue-61801-path-pattern-can-infer.rs | 2 +- .../type-alias-impl-trait/assoc-type-const.rs | 36 + .../assoc-type-const.stderr | 8 + .../assoc-type-lifetime.rs | 28 + .../type-alias-impl-trait/bound_reduction2.rs | 1 + .../bound_reduction2.stderr | 16 +- src/test/ui/type-alias-impl-trait/fallback.rs | 28 + .../generic_nondefining_use.stderr | 6 +- .../generic_not_used.stderr | 4 +- ..._type_does_not_live_long_enough.nll.stderr | 12 +- ...eric_type_does_not_live_long_enough.stderr | 12 +- .../generic_underconstrained.stderr | 4 +- .../generic_underconstrained2.stderr | 8 +- .../ui/type-alias-impl-trait/issue-58887.rs | 5 +- .../type-alias-impl-trait/issue-58887.stderr | 30 - .../type-alias-impl-trait/issue-60371.stderr | 4 +- .../ui/type-alias-impl-trait/issue-60564.rs | 2 +- .../type-alias-impl-trait/issue-60564.stderr | 7 +- .../issue-63263-closure-return.rs | 13 + .../ui/type-alias-impl-trait/issue-63279.rs | 9 + .../type-alias-impl-trait/issue-63279.stderr | 13 + .../issue-66580-closure-coherence.rs | 19 + .../never_reveal_concrete_type.stderr | 8 +- ...o_revealing_outside_defining_module.stderr | 14 +- .../not_a_defining_use.stderr | 2 +- ...ype-alias-impl-trait-with-no-traits.stderr | 4 +- .../unused_generic_param.stderr | 8 +- .../or_else-multiple-type-params.rs | 10 + .../or_else-multiple-type-params.stderr | 12 + src/test/ui/type-inference/sort_by_key.rs | 5 + src/test/ui/type-inference/sort_by_key.stderr | 11 + .../unbounded-associated-type.rs | 16 + .../unbounded-associated-type.stderr | 15 + ...ounded-type-param-in-fn-with-assoc-type.rs | 9 + ...ed-type-param-in-fn-with-assoc-type.stderr | 9 + .../unbounded-type-param-in-fn.rs | 7 + .../unbounded-type-param-in-fn.stderr | 9 + src/test/ui/type/ascription/issue-34255-1.rs | 1 - .../ui/type/ascription/issue-34255-1.stderr | 10 +- .../ui/type/ascription/issue-54516.stderr | 2 +- .../ui/type/ascription/issue-60933.stderr | 2 +- src/test/ui/type/type-annotation-needed.rs | 2 + .../ui/type/type-annotation-needed.stderr | 7 +- .../ui/type/type-ascription-precedence.stderr | 21 +- .../ui/type/type-ascription-soundness.stderr | 24 +- src/test/ui/type/type-check-defaults.rs | 4 +- src/test/ui/type/type-check-defaults.stderr | 8 +- .../assignment-expected-bool.stderr | 62 +- .../type/type-check/assignment-in-if.stderr | 30 +- .../cannot_infer_local_or_vec.stderr | 2 +- ...cannot_infer_local_or_vec_in_tuples.stderr | 2 +- .../ui/type/type-check/issue-22897.stderr | 2 +- .../ui/type/type-check/issue-40294.stderr | 6 +- ...ment-match-prior-arm-bool-expected-unit.rs | 27 + ...-match-prior-arm-bool-expected-unit.stderr | 22 + .../ui/type/type-dependent-def-issue-49241.rs | 2 +- .../type-dependent-def-issue-49241.stderr | 4 +- src/test/ui/type/type-error-break-tail.rs | 8 + src/test/ui/type/type-error-break-tail.stderr | 15 + src/test/ui/type/type-mismatch-multiple.rs | 6 +- .../ui/type/type-mismatch-multiple.stderr | 11 +- .../ui/type/type-mismatch-same-crate-name.rs | 10 +- .../type/type-mismatch-same-crate-name.stderr | 20 +- src/test/ui/type/type-mismatch.stderr | 226 +- src/test/ui/type/type-parameter-names.rs | 6 +- src/test/ui/type/type-parameter-names.stderr | 11 +- .../type/type-params-in-different-spaces-1.rs | 6 +- .../type-params-in-different-spaces-1.stderr | 16 +- .../type-params-in-different-spaces-3.stderr | 18 +- src/test/ui/type/type-shadow.stderr | 7 +- src/test/ui/type_length_limit.rs | 3 +- ...10-must-typeck-match-pats-before-guards.rs | 2 +- ...e-57673-ice-on-deref-of-boxed-trait.stderr | 6 +- .../typeck_type_placeholder_mismatch.rs | 8 +- .../typeck_type_placeholder_mismatch.stderr | 16 +- src/test/ui/ufcs/ufcs-explicit-self-bad.rs | 8 +- .../ui/ufcs/ufcs-explicit-self-bad.stderr | 16 +- .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 4 +- .../unboxed-closures/issue-30906.nll.stderr | 8 + src/test/ui/unboxed-closures/issue-30906.rs | 18 + .../ui/unboxed-closures/issue-30906.stderr | 12 + .../unboxed-closure-immutable-capture.stderr | 3 +- ...-infer-fn-once-move-from-projection.stderr | 2 +- .../unboxed-closures-mutate-upvar.stderr | 1 + ...sures-mutated-upvar-from-fn-closure.stderr | 1 + .../unboxed-closures-type-mismatch.stderr | 2 +- src/test/ui/unconstrained-none.stderr | 2 +- src/test/ui/unconstrained-ref.stderr | 2 +- .../dyn-trait-underscore.stderr | 10 +- ...underscore-lifetime-elison-mismatch.stderr | 1 + .../where-clause-inherent-impl-underscore.rs | 3 +- .../where-clause-trait-impl-region.rs | 3 +- .../where-clause-trait-impl-underscore.rs | 3 +- .../uninhabited-matches-feature-gated.stderr | 7 +- src/test/ui/union/union-fields-1.rs | 8 +- src/test/ui/union/union-fields-1.stderr | 8 +- src/test/ui/union/union-lint-dead-code.rs | 2 +- src/test/ui/union/union-lint-dead-code.stderr | 2 +- src/test/ui/unop-move-semantics.stderr | 4 +- ...ad-code-ret.rs => unreachable-code-ret.rs} | 0 ...ret.stderr => unreachable-code-ret.stderr} | 4 +- .../unsafe/unsafe-block-without-braces.stderr | 2 +- src/test/ui/unsafe/unsafe-subtyping.stderr | 4 +- src/test/ui/unsafe/unsafe-trait-impl.rs | 4 +- src/test/ui/unsafe/unsafe-trait-impl.stderr | 4 +- src/test/ui/unsized/unsized-fn-param.rs | 20 + src/test/ui/unsized/unsized-fn-param.stderr | 43 + .../variance-btree-invariant-types.nll.stderr | 24 + .../variance-btree-invariant-types.stderr | 48 +- .../variance-cell-is-invariant.nll.stderr | 2 + .../variance-cell-is-invariant.stderr | 1 + ...riance-contravariant-arg-object.nll.stderr | 4 + .../variance-contravariant-arg-object.stderr | 8 +- ...e-contravariant-arg-trait-match.nll.stderr | 4 + ...-contravariant-self-trait-match.nll.stderr | 4 + .../variance-covariant-arg-object.nll.stderr | 4 + .../variance-covariant-arg-object.stderr | 8 +- ...iance-covariant-arg-trait-match.nll.stderr | 4 + ...ance-covariant-self-trait-match.nll.stderr | 4 + .../variance-invariant-arg-object.nll.stderr | 4 + .../variance-invariant-arg-object.stderr | 8 +- ...iance-invariant-arg-trait-match.nll.stderr | 4 + ...ance-invariant-self-trait-match.nll.stderr | 4 + ...ance-use-contravariant-struct-1.nll.stderr | 2 + ...variance-use-contravariant-struct-1.stderr | 4 +- ...variance-use-covariant-struct-1.nll.stderr | 2 + .../variance-use-covariant-struct-1.stderr | 4 +- ...variance-use-invariant-struct-1.nll.stderr | 4 + .../variance-use-invariant-struct-1.stderr | 8 +- src/test/ui/vector-no-ann.stderr | 2 +- src/test/ui/wf/wf-static-method.nll.stderr | 12 + .../ui/wf/wf-unsafe-trait-obj-match.stderr | 4 +- src/test/ui/while-type-error.stderr | 4 +- src/test/ui/wrong-mul-method-signature.stderr | 28 +- src/test/ui/wrong-ret-type.stderr | 7 +- src/tools/build-manifest/Cargo.toml | 1 + src/tools/build-manifest/src/main.rs | 23 +- src/tools/compiletest/src/errors.rs | 90 +- src/tools/compiletest/src/header.rs | 42 +- src/tools/compiletest/src/json.rs | 2 +- src/tools/compiletest/src/main.rs | 166 +- src/tools/compiletest/src/runtest.rs | 200 +- src/tools/error_index_generator/build.rs | 31 +- src/tools/publish_toolstate.py | 8 +- src/tools/rustbook/Cargo.toml | 8 +- src/tools/rustbook/src/main.rs | 33 +- src/tools/rustdoc-themes/main.rs | 6 +- src/tools/tidy/src/deps.rs | 5 + src/tools/tidy/src/error_codes_check.rs | 68 +- src/tools/tidy/src/features.rs | 11 +- src/tools/tidy/src/style.rs | 32 +- vendor/cc/.cargo-checksum.json | 2 +- vendor/cc/Cargo.lock | 154 + vendor/cc/Cargo.toml | 13 +- vendor/cc/README.md | 8 - vendor/cc/azure-pipelines.yml | 101 - vendor/cc/ci/azure-install-rust.yml | 24 - vendor/cc/ci/azure-steps.yml | 21 - vendor/cc/src/bin/gcc-shim.rs | 39 +- vendor/cc/src/com.rs | 14 +- vendor/cc/src/lib.rs | 484 +- vendor/cc/src/setup_config.rs | 24 +- vendor/cc/src/windows_registry.rs | 157 +- vendor/cc/tests/cc_env.rs | 5 +- vendor/cc/tests/cflags.rs | 15 + vendor/cc/tests/cxxflags.rs | 15 + vendor/cc/tests/support/mod.rs | 48 +- vendor/cc/tests/test.rs | 78 +- .../codespan-reporting/.cargo-checksum.json | 1 + vendor/codespan-reporting/Cargo.lock | 663 + vendor/codespan-reporting/Cargo.toml | 60 + vendor/codespan-reporting/README.md | 33 + vendor/codespan-reporting/examples/term.rs | 153 + vendor/codespan-reporting/src/diagnostic.rs | 160 + vendor/codespan-reporting/src/lib.rs | 4 + vendor/codespan-reporting/src/term/config.rs | 255 + vendor/codespan-reporting/src/term/mod.rs | 90 + .../src/term/views/diagnostic.rs | 93 + .../src/term/views/header.rs | 70 + .../src/term/views/locus.rs | 37 + .../codespan-reporting/src/term/views/mod.rs | 11 + .../src/term/views/new_line.rs | 17 + .../src/term/views/source_snippet/border.rs | 76 + .../src/term/views/source_snippet/gutter.rs | 47 + .../src/term/views/source_snippet/mod.rs | 333 + .../src/term/views/source_snippet/note.rs | 62 + .../term/views/source_snippet/underline.rs | 203 + .../snapshots/empty_spans__rich_color.snap | 31 + .../snapshots/empty_spans__rich_no_color.snap | 31 + .../snapshots/fizz_buzz__rich_color.snap | 54 + .../snapshots/fizz_buzz__rich_no_color.snap | 54 + .../snapshots/fizz_buzz__short_color.snap | 9 + .../snapshots/fizz_buzz__short_no_color.snap | 9 + .../snapshots/multifile__rich_color.snap | 39 + .../snapshots/multifile__rich_no_color.snap | 39 + .../snapshots/multifile__short_color.snap | 10 + .../snapshots/multifile__short_no_color.snap | 10 + .../tabbed__tab_width_3_no_color.snap | 31 + .../tabbed__tab_width_6_no_color.snap | 31 + .../tabbed__tab_width_default_no_color.snap | 31 + .../tests/support/color_buffer.rs | 137 + .../codespan-reporting/tests/support/mod.rs | 31 + vendor/codespan-reporting/tests/term.rs | 347 + vendor/codespan/.cargo-checksum.json | 1 + vendor/codespan/Cargo.toml | 44 + vendor/codespan/src/file.rs | 404 + vendor/codespan/src/index.rs | 430 + vendor/codespan/src/lib.rs | 27 + vendor/codespan/src/location.rs | 25 + vendor/codespan/src/span.rs | 111 + vendor/compiler_builtins/.cargo-checksum.json | 2 +- vendor/compiler_builtins/Cargo.lock | 14 +- vendor/compiler_builtins/Cargo.toml | 8 +- vendor/compiler_builtins/README.md | 12 +- vendor/compiler_builtins/build.rs | 8 + .../compiler_builtins/examples/intrinsics.rs | 1 - .../compiler_builtins/libm/src/math/acos.rs | 2 - .../compiler_builtins/libm/src/math/acosf.rs | 2 - .../compiler_builtins/libm/src/math/asin.rs | 2 - .../compiler_builtins/libm/src/math/asinf.rs | 2 - .../compiler_builtins/libm/src/math/atan.rs | 1 - .../compiler_builtins/libm/src/math/atan2.rs | 1 - .../compiler_builtins/libm/src/math/atan2f.rs | 1 - .../compiler_builtins/libm/src/math/atanf.rs | 1 - .../compiler_builtins/libm/src/math/cbrt.rs | 1 - .../compiler_builtins/libm/src/math/cbrtf.rs | 1 - .../compiler_builtins/libm/src/math/ceil.rs | 18 +- .../compiler_builtins/libm/src/math/ceilf.rs | 23 +- vendor/compiler_builtins/libm/src/math/cos.rs | 1 - .../compiler_builtins/libm/src/math/cosf.rs | 1 - .../compiler_builtins/libm/src/math/cosh.rs | 1 - .../compiler_builtins/libm/src/math/coshf.rs | 1 - vendor/compiler_builtins/libm/src/math/exp.rs | 1 - .../compiler_builtins/libm/src/math/exp2.rs | 1 - .../compiler_builtins/libm/src/math/exp2f.rs | 1 - .../compiler_builtins/libm/src/math/expf.rs | 1 - .../compiler_builtins/libm/src/math/expm1.rs | 1 - .../compiler_builtins/libm/src/math/expm1f.rs | 1 - .../compiler_builtins/libm/src/math/expo2.rs | 1 - .../compiler_builtins/libm/src/math/fabs.rs | 25 +- .../compiler_builtins/libm/src/math/fabsf.rs | 25 +- .../compiler_builtins/libm/src/math/fdim.rs | 1 - .../compiler_builtins/libm/src/math/fdimf.rs | 1 - .../compiler_builtins/libm/src/math/fenv.rs | 18 +- .../compiler_builtins/libm/src/math/floor.rs | 23 +- .../compiler_builtins/libm/src/math/floorf.rs | 22 +- vendor/compiler_builtins/libm/src/math/fma.rs | 26 +- .../compiler_builtins/libm/src/math/fmaf.rs | 1 - .../compiler_builtins/libm/src/math/fmax.rs | 1 - .../compiler_builtins/libm/src/math/fmaxf.rs | 1 - .../compiler_builtins/libm/src/math/fmin.rs | 1 - .../compiler_builtins/libm/src/math/fminf.rs | 1 - .../compiler_builtins/libm/src/math/fmod.rs | 1 - .../compiler_builtins/libm/src/math/fmodf.rs | 1 - .../compiler_builtins/libm/src/math/hypot.rs | 2 - .../compiler_builtins/libm/src/math/hypotf.rs | 1 - vendor/compiler_builtins/libm/src/math/j1f.rs | 16 +- .../compiler_builtins/libm/src/math/k_cos.rs | 1 - .../compiler_builtins/libm/src/math/k_cosf.rs | 1 - .../libm/src/math/k_expo2.rs | 1 - .../libm/src/math/k_expo2f.rs | 1 - .../compiler_builtins/libm/src/math/k_sin.rs | 1 - .../compiler_builtins/libm/src/math/k_sinf.rs | 1 - .../compiler_builtins/libm/src/math/k_tan.rs | 2 - .../compiler_builtins/libm/src/math/k_tanf.rs | 1 - .../compiler_builtins/libm/src/math/ldexp.rs | 1 - .../compiler_builtins/libm/src/math/ldexpf.rs | 1 - .../libm/src/math/lgamma_r.rs | 4 +- .../libm/src/math/lgammaf_r.rs | 4 +- vendor/compiler_builtins/libm/src/math/log.rs | 1 - .../compiler_builtins/libm/src/math/log10.rs | 1 - .../compiler_builtins/libm/src/math/log10f.rs | 1 - .../compiler_builtins/libm/src/math/log1p.rs | 1 - .../compiler_builtins/libm/src/math/log1pf.rs | 1 - .../compiler_builtins/libm/src/math/log2.rs | 1 - .../compiler_builtins/libm/src/math/log2f.rs | 1 - .../compiler_builtins/libm/src/math/logf.rs | 1 - vendor/compiler_builtins/libm/src/math/mod.rs | 14 +- .../libm/src/math/nextafter.rs | 37 + .../libm/src/math/nextafterf.rs | 37 + vendor/compiler_builtins/libm/src/math/pow.rs | 3 +- .../compiler_builtins/libm/src/math/powf.rs | 1 - .../libm/src/math/rem_pio2.rs | 55 +- .../libm/src/math/rem_pio2_large.rs | 7 +- .../libm/src/math/rem_pio2f.rs | 1 - .../libm/src/math/remainder.rs | 5 + .../libm/src/math/remainderf.rs | 5 + .../compiler_builtins/libm/src/math/remquo.rs | 15 +- .../libm/src/math/remquof.rs | 1 + .../compiler_builtins/libm/src/math/round.rs | 21 +- .../compiler_builtins/libm/src/math/roundf.rs | 17 +- .../compiler_builtins/libm/src/math/scalbn.rs | 1 - .../libm/src/math/scalbnf.rs | 1 - vendor/compiler_builtins/libm/src/math/sin.rs | 1 - .../compiler_builtins/libm/src/math/sincos.rs | 4 +- .../libm/src/math/sincosf.rs | 4 +- .../compiler_builtins/libm/src/math/sinf.rs | 1 - .../compiler_builtins/libm/src/math/sinh.rs | 1 - .../compiler_builtins/libm/src/math/sinhf.rs | 1 - .../compiler_builtins/libm/src/math/sqrt.rs | 259 +- .../compiler_builtins/libm/src/math/sqrtf.rs | 174 +- vendor/compiler_builtins/libm/src/math/tan.rs | 1 - .../compiler_builtins/libm/src/math/tanf.rs | 1 - .../compiler_builtins/libm/src/math/tanh.rs | 1 - .../compiler_builtins/libm/src/math/tanhf.rs | 1 - .../compiler_builtins/libm/src/math/trunc.rs | 1 - .../compiler_builtins/libm/src/math/truncf.rs | 1 - vendor/compiler_builtins/src/lib.rs | 35 +- vendor/compiler_builtins/src/mem.rs | 134 + vendor/compiler_builtins/src/probestack.rs | 225 +- vendor/compiler_builtins/src/x86_64.rs | 7 + .../.cargo-checksum.json | 0 .../CHANGELOG.md | 0 .../Cargo.toml | 0 .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 .../README.md | 0 .../benches/atomic_cell.rs | 0 .../src/atomic/atomic_cell.rs | 0 .../src/atomic/consume.rs | 0 .../src/atomic/mod.rs | 0 .../src/backoff.rs | 0 .../src/cache_padded.rs | 0 .../src/lib.rs | 0 .../src/sync/mod.rs | 0 .../src/sync/parker.rs | 0 .../src/sync/sharded_lock.rs | 0 .../src/sync/wait_group.rs | 0 .../src/thread.rs | 0 .../tests/atomic_cell.rs | 0 .../tests/cache_padded.rs | 0 .../tests/parker.rs | 0 .../tests/sharded_lock.rs | 0 .../tests/thread.rs | 0 .../tests/wait_group.rs | 0 vendor/flate2/.cargo-checksum.json | 2 +- vendor/flate2/Cargo.lock | 600 + vendor/flate2/Cargo.toml | 43 +- vendor/flate2/README.md | 22 +- vendor/flate2/appveyor.yml | 28 - .../flate2/examples/deflatedecoder-bufread.rs | 8 +- vendor/flate2/examples/deflatedecoder-read.rs | 8 +- .../flate2/examples/deflatedecoder-write.rs | 8 +- .../flate2/examples/deflateencoder-bufread.rs | 6 +- vendor/flate2/examples/deflateencoder-read.rs | 6 +- .../flate2/examples/deflateencoder-write.rs | 4 +- vendor/flate2/examples/gzbuilder.rs | 8 +- vendor/flate2/examples/gzdecoder-bufread.rs | 8 +- vendor/flate2/examples/gzdecoder-read.rs | 8 +- vendor/flate2/examples/gzdecoder-write.rs | 6 +- vendor/flate2/examples/gzencoder-bufread.rs | 6 +- vendor/flate2/examples/gzencoder-read.rs | 6 +- vendor/flate2/examples/gzencoder-write.rs | 4 +- .../flate2/examples/gzmultidecoder-bufread.rs | 8 +- vendor/flate2/examples/gzmultidecoder-read.rs | 8 +- vendor/flate2/examples/zlibdecoder-bufread.rs | 8 +- vendor/flate2/examples/zlibdecoder-read.rs | 8 +- vendor/flate2/examples/zlibdecoder-write.rs | 8 +- vendor/flate2/examples/zlibencoder-bufread.rs | 6 +- vendor/flate2/examples/zlibencoder-read.rs | 4 +- vendor/flate2/examples/zlibencoder-write.rs | 4 +- vendor/flate2/src/crc.rs | 9 +- vendor/flate2/src/deflate/bufread.rs | 8 +- vendor/flate2/src/deflate/mod.rs | 16 +- vendor/flate2/src/deflate/read.rs | 6 +- vendor/flate2/src/deflate/write.rs | 12 +- vendor/flate2/src/ffi.rs | 167 - vendor/flate2/src/ffi/c.rs | 413 + vendor/flate2/src/ffi/mod.rs | 51 + vendor/flate2/src/ffi/rust.rs | 183 + vendor/flate2/src/gz/bufread.rs | 369 +- vendor/flate2/src/gz/mod.rs | 12 +- vendor/flate2/src/gz/read.rs | 33 +- vendor/flate2/src/gz/write.rs | 11 +- vendor/flate2/src/lib.rs | 125 +- vendor/flate2/src/mem.rs | 269 +- vendor/flate2/src/zio.rs | 4 +- vendor/flate2/src/zlib/bufread.rs | 8 +- vendor/flate2/src/zlib/mod.rs | 16 +- vendor/flate2/src/zlib/read.rs | 6 +- vendor/flate2/src/zlib/write.rs | 12 +- vendor/flate2/tests/async-reader.rs | 96 + vendor/flate2/tests/early-flush.rs | 2 +- vendor/flate2/tests/gunzip.rs | 4 +- vendor/flate2/tests/tokio.rs | 34 +- vendor/idna-0.1.5/.cargo-checksum.json | 1 + .../Cargo.toml | 27 +- .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 vendor/idna-0.1.5/src/IdnaMappingTable.txt | 8405 ++++++++ vendor/idna-0.1.5/src/lib.rs | 73 + .../src/make_uts46_mapping_table.py | 192 + vendor/idna-0.1.5/src/punycode.rs | 213 + vendor/idna-0.1.5/src/uts46.rs | 433 + vendor/idna-0.1.5/src/uts46_mapping_table.rs | 16005 ++++++++++++++++ vendor/idna-0.1.5/tests/IdnaTest.txt | 7848 ++++++++ vendor/idna-0.1.5/tests/punycode.rs | 65 + vendor/idna-0.1.5/tests/punycode_tests.json | 120 + vendor/idna-0.1.5/tests/tests.rs | 21 + vendor/idna-0.1.5/tests/unit.rs | 40 + vendor/idna-0.1.5/tests/uts46.rs | 124 + vendor/itertools-0.7.8/.cargo-checksum.json | 1 + vendor/itertools-0.7.8/Cargo.toml | 43 + .../LICENSE-APACHE | 0 vendor/itertools-0.7.8/LICENSE-MIT | 25 + vendor/itertools-0.7.8/Makefile | 34 + vendor/itertools-0.7.8/README.rst | 490 + vendor/itertools-0.7.8/benches/bench1.rs | 735 + vendor/itertools-0.7.8/benches/extra/mod.rs | 4 + .../benches/extra/zipslices.rs | 189 + vendor/itertools-0.7.8/benches/tree_fold1.rs | 126 + .../benches/tuple_combinations.rs | 97 + vendor/itertools-0.7.8/benches/tuples.rs | 190 + vendor/itertools-0.7.8/bors.toml | 3 + vendor/itertools-0.7.8/custom.css | 29 + vendor/itertools-0.7.8/examples/iris.data | 150 + vendor/itertools-0.7.8/examples/iris.rs | 141 + vendor/itertools-0.7.8/src/adaptors/mod.rs | 1293 ++ .../src/adaptors/multi_product.rs | 220 + vendor/itertools-0.7.8/src/combinations.rs | 165 + vendor/itertools-0.7.8/src/concat_impl.rs | 22 + .../itertools-0.7.8/src/cons_tuples_impl.rs | 68 + vendor/itertools-0.7.8/src/diff.rs | 61 + vendor/itertools-0.7.8/src/either_or_both.rs | 10 + vendor/itertools-0.7.8/src/format.rs | 113 + vendor/itertools-0.7.8/src/free.rs | 231 + vendor/itertools-0.7.8/src/group_map.rs | 22 + vendor/itertools-0.7.8/src/groupbylazy.rs | 571 + vendor/itertools-0.7.8/src/impl_macros.rs | 14 + vendor/itertools-0.7.8/src/intersperse.rs | 60 + vendor/itertools-0.7.8/src/kmerge_impl.rs | 256 + vendor/itertools-0.7.8/src/lib.rs | 2121 ++ vendor/itertools-0.7.8/src/merge_join.rs | 87 + vendor/itertools-0.7.8/src/minmax.rs | 114 + vendor/itertools-0.7.8/src/multipeek_impl.rs | 104 + vendor/itertools-0.7.8/src/pad_tail.rs | 83 + .../itertools-0.7.8/src/peeking_take_while.rs | 149 + .../src/process_results_impl.rs | 81 + vendor/itertools-0.7.8/src/put_back_n_impl.rs | 63 + vendor/itertools-0.7.8/src/rciter_impl.rs | 98 + vendor/itertools-0.7.8/src/repeatn.rs | 54 + vendor/itertools-0.7.8/src/size_hint.rs | 104 + vendor/itertools-0.7.8/src/sources.rs | 187 + vendor/itertools-0.7.8/src/tee.rs | 78 + vendor/itertools-0.7.8/src/tuple_impl.rs | 266 + vendor/itertools-0.7.8/src/unique_impl.rs | 134 + vendor/itertools-0.7.8/src/with_position.rs | 90 + vendor/itertools-0.7.8/src/zip_eq_impl.rs | 60 + vendor/itertools-0.7.8/src/zip_longest.rs | 78 + vendor/itertools-0.7.8/src/ziptuple.rs | 111 + vendor/itertools-0.7.8/tests/merge_join.rs | 110 + .../tests/peeking_take_while.rs | 53 + vendor/itertools-0.7.8/tests/quick.rs | 1019 + vendor/itertools-0.7.8/tests/test_core.rs | 240 + vendor/itertools-0.7.8/tests/test_std.rs | 749 + vendor/itertools-0.7.8/tests/tuples.rs | 88 + vendor/itertools-0.7.8/tests/zip.rs | 65 + vendor/measureme/.cargo-checksum.json | 2 +- vendor/measureme/Cargo.toml | 7 +- .../measureme/benches/serialization_bench.rs | 23 - vendor/measureme/src/event.rs | 13 - vendor/measureme/src/file_header.rs | 10 +- .../measureme/src/file_serialization_sink.rs | 75 +- vendor/measureme/src/lib.rs | 46 +- vendor/measureme/src/profiler.rs | 69 +- vendor/measureme/src/profiling_data.rs | 154 - vendor/measureme/src/raw_event.rs | 347 +- vendor/measureme/src/serialization.rs | 68 +- vendor/measureme/src/stringtable.rs | 347 +- vendor/measureme/src/testing_common.rs | 109 - vendor/measureme/tests/serialization.rs | 12 - vendor/memmap/.cargo-checksum.json | 2 +- vendor/memmap/Cargo.toml | 2 +- vendor/memmap/ci/install.sh | 28 +- vendor/memmap/ci/script.sh | 7 +- vendor/memmap/examples/cat.rs | 2 +- vendor/memmap/src/lib.rs | 65 +- vendor/memmap/src/unix.rs | 30 +- vendor/memmap/src/windows.rs | 58 +- vendor/memoffset-0.2.1/.cargo-checksum.json | 1 - vendor/memoffset-0.2.1/Cargo.toml | 24 - vendor/memoffset-0.2.1/LICENSE | 19 - vendor/memoffset-0.2.1/README.md | 47 - vendor/memoffset-0.2.1/src/lib.rs | 70 - vendor/memoffset-0.2.1/src/offset_of.rs | 119 - vendor/memoffset-0.2.1/src/span_of.rs | 274 - vendor/num_cpus/.cargo-checksum.json | 2 +- vendor/num_cpus/CHANGELOG.md | 19 + vendor/num_cpus/Cargo.toml | 6 +- vendor/num_cpus/examples/values.rs | 6 + vendor/num_cpus/src/lib.rs | 101 +- .../.cargo-checksum.json | 1 - vendor/percent-encoding-1.0.1/lib.rs | 442 - vendor/percent-encoding/.cargo-checksum.json | 2 +- vendor/percent-encoding/Cargo.toml | 2 +- vendor/percent-encoding/lib.rs | 6 + vendor/polonius-engine/.cargo-checksum.json | 2 +- vendor/polonius-engine/Cargo.toml | 2 +- vendor/polonius-engine/src/facts.rs | 109 +- vendor/polonius-engine/src/lib.rs | 1 + .../src/output/datafrog_opt.rs | 529 +- vendor/polonius-engine/src/output/hybrid.rs | 29 - .../src/output/initialization.rs | 127 +- vendor/polonius-engine/src/output/liveness.rs | 233 +- .../src/output/location_insensitive.rs | 143 +- vendor/polonius-engine/src/output/mod.rs | 451 +- vendor/polonius-engine/src/output/naive.rs | 302 +- vendor/rand_core-0.4.0/.cargo-checksum.json | 1 + vendor/rand_core-0.4.0/CHANGELOG.md | 36 + vendor/rand_core-0.4.0/COPYRIGHT | 12 + vendor/rand_core-0.4.0/Cargo.toml | 41 + vendor/rand_core-0.4.0/LICENSE-APACHE | 201 + vendor/rand_core-0.4.0/LICENSE-MIT | 26 + vendor/rand_core-0.4.0/README.md | 66 + vendor/rand_core-0.4.0/src/block.rs | 499 + vendor/rand_core-0.4.0/src/error.rs | 177 + vendor/rand_core-0.4.0/src/impls.rs | 165 + vendor/rand_core-0.4.0/src/le.rs | 68 + vendor/rand_core-0.4.0/src/lib.rs | 477 + vendor/rand_core/.cargo-checksum.json | 2 +- vendor/rand_core/CHANGELOG.md | 23 +- vendor/rand_core/Cargo.toml | 12 +- vendor/rand_core/src/block.rs | 12 +- vendor/rand_core/src/error.rs | 62 +- vendor/rand_core/src/impls.rs | 15 +- vendor/rand_core/src/lib.rs | 23 +- vendor/rand_core/src/os.rs | 85 + vendor/smallvec-0.6.10/.cargo-checksum.json | 1 + vendor/smallvec-0.6.10/Cargo.toml | 39 + vendor/smallvec-0.6.10/LICENSE-APACHE | 201 + vendor/smallvec-0.6.10/LICENSE-MIT | 25 + vendor/smallvec-0.6.10/README.md | 8 + vendor/smallvec-0.6.10/benches/bench.rs | 295 + vendor/smallvec-0.6.10/lib.rs | 2360 +++ vendor/smallvec/.cargo-checksum.json | 2 +- vendor/smallvec/Cargo.toml | 6 +- vendor/smallvec/lib.rs | 768 +- vendor/smallvec/scripts/run_miri.sh | 21 + vendor/smallvec/specialization.rs | 19 + vendor/syn/.cargo-checksum.json | 2 +- vendor/syn/Cargo.toml | 24 +- vendor/syn/src/attr.rs | 37 + vendor/syn/src/buffer.rs | 1 - vendor/syn/src/data.rs | 55 +- vendor/syn/src/discouraged.rs | 24 + vendor/syn/src/expr.rs | 41 +- vendor/syn/src/generics.rs | 8 +- vendor/syn/src/item.rs | 116 +- vendor/syn/src/lib.rs | 13 +- vendor/syn/src/lit.rs | 2 +- vendor/syn/src/macros.rs | 25 +- vendor/syn/src/parse.rs | 98 +- vendor/syn/src/pat.rs | 24 +- vendor/syn/src/token.rs | 3 +- vendor/syn/src/tt.rs | 6 +- vendor/syn/src/ty.rs | 76 +- vendor/syn/tests/clone.sh | 16 - vendor/syn/tests/common/eq.rs | 110 +- vendor/syn/tests/common/parse.rs | 14 +- vendor/syn/tests/debug/mod.rs | 7 +- vendor/syn/tests/macros/mod.rs | 8 +- vendor/syn/tests/repo/mod.rs | 56 +- vendor/syn/tests/test_asyncness.rs | 36 +- vendor/syn/tests/test_attribute.rs | 408 +- vendor/syn/tests/test_derive_input.rs | 1319 +- vendor/syn/tests/test_expr.rs | 27 +- vendor/syn/tests/test_generics.rs | 367 +- vendor/syn/tests/test_grouping.rs | 49 +- vendor/syn/tests/test_ident.rs | 3 - vendor/syn/tests/test_iterators.rs | 5 +- vendor/syn/tests/test_lit.rs | 4 - vendor/syn/tests/test_meta.rs | 496 +- vendor/syn/tests/test_parse_buffer.rs | 4 +- vendor/syn/tests/test_pat.rs | 3 - vendor/syn/tests/test_precedence.rs | 20 +- vendor/syn/tests/test_receiver.rs | 109 + vendor/syn/tests/test_round_trip.rs | 10 +- vendor/syn/tests/test_should_parse.rs | 2 - vendor/syn/tests/test_token_trees.rs | 4 - vendor/syn/tests/test_visibility.rs | 99 + vendor/syn/tests/zzz_stable.rs | 2 - vendor/time/.cargo-checksum.json | 2 +- vendor/time/Cargo.toml | 2 +- vendor/time/src/duration.rs | 8 +- vendor/time/src/lib.rs | 4 +- vendor/time/src/sys.rs | 77 + .../unicode-segmentation/.cargo-checksum.json | 2 +- vendor/unicode-segmentation/Cargo.toml | 10 +- vendor/unicode-segmentation/README.md | 28 +- .../unicode-segmentation/scripts/unicode.py | 58 +- .../scripts/unicode_gen_breaktests.py | 37 +- vendor/unicode-segmentation/src/grapheme.rs | 24 +- vendor/unicode-segmentation/src/lib.rs | 46 +- vendor/unicode-segmentation/src/sentence.rs | 373 + vendor/unicode-segmentation/src/tables.rs | 3272 +++- vendor/unicode-segmentation/src/test.rs | 23 +- vendor/unicode-segmentation/src/testdata.rs | 2412 +-- vendor/unicode-segmentation/src/word.rs | 73 +- .../.cargo-checksum.json | 0 .../Cargo.toml | 0 vendor/version_check-0.1.5/LICENSE-APACHE | 201 + .../LICENSE-MIT | 0 .../README.md | 0 .../src/lib.rs | 0 vendor/wasi-0.7.0/.cargo-checksum.json | 1 + vendor/{wasi => wasi-0.7.0}/0001-maybe.patch | 0 vendor/wasi-0.7.0/CODE_OF_CONDUCT.md | 46 + vendor/wasi-0.7.0/CONTRIBUTING.md | 8 + vendor/wasi-0.7.0/Cargo.toml | 43 + vendor/wasi-0.7.0/LICENSE-APACHE | 201 + .../LICENSE-Apache-2.0_WITH_LLVM-exception | 220 + vendor/wasi-0.7.0/LICENSE-MIT | 23 + vendor/wasi-0.7.0/README.md | 24 + vendor/{wasi => wasi-0.7.0}/clip.log | 0 vendor/wasi-0.7.0/old-bitflags.patch | 570 + vendor/{wasi => wasi-0.7.0}/rusty-tags.vi | 0 vendor/wasi-0.7.0/src/lib.rs | 20 + .../src/wasi_unstable/mod.rs | 0 .../src/wasi_unstable/raw.rs | 0 vendor/wasi/.cargo-checksum.json | 2 +- vendor/wasi/CODE_OF_CONDUCT.md | 11 +- vendor/wasi/Cargo.toml | 8 +- vendor/wasi/ORG_CODE_OF_CONDUCT.md | 143 + vendor/wasi/README.md | 78 +- vendor/wasi/SECURITY.md | 29 + vendor/wasi/src/error.rs | 51 + vendor/wasi/src/lib.rs | 52 +- vendor/wasi/src/lib_generated.rs | 1853 ++ vendor/winapi/.cargo-checksum.json | 2 +- vendor/winapi/Cargo.toml | 39 +- vendor/winapi/README.md | 7 + vendor/winapi/build.rs | 57 +- vendor/winapi/src/km/d3dkmthk.rs | 312 + vendor/winapi/src/km/mod.rs | 7 + vendor/winapi/src/lib.rs | 6 +- vendor/winapi/src/macros.rs | 50 +- vendor/winapi/src/shared/basetsd.rs | 17 +- vendor/winapi/src/shared/bcrypt.rs | 1 - vendor/winapi/src/shared/bthdef.rs | 1103 ++ vendor/winapi/src/shared/bthioctl.rs | 151 + vendor/winapi/src/shared/bthsdpdef.rs | 68 + vendor/winapi/src/shared/bugcodes.rs | 1 - vendor/winapi/src/shared/cderr.rs | 1 - vendor/winapi/src/shared/cfg.rs | 1 - vendor/winapi/src/shared/d3d9.rs | 1 - vendor/winapi/src/shared/d3d9caps.rs | 1 - vendor/winapi/src/shared/d3d9types.rs | 1 - vendor/winapi/src/shared/d3dkmdt.rs | 45 + vendor/winapi/src/shared/d3dukmdt.rs | 416 + vendor/winapi/src/shared/dcomptypes.rs | 1 - vendor/winapi/src/shared/devguid.rs | 1 - vendor/winapi/src/shared/devpkey.rs | 1 - vendor/winapi/src/shared/devpropdef.rs | 1 - vendor/winapi/src/shared/dinputd.rs | 1 - vendor/winapi/src/shared/dxgi.rs | 1 - vendor/winapi/src/shared/dxgi1_2.rs | 1 - vendor/winapi/src/shared/dxgi1_3.rs | 1 - vendor/winapi/src/shared/dxgi1_4.rs | 1 - vendor/winapi/src/shared/dxgi1_5.rs | 1 - vendor/winapi/src/shared/dxgi1_6.rs | 1 - vendor/winapi/src/shared/dxgiformat.rs | 1 - vendor/winapi/src/shared/dxgitype.rs | 1 - vendor/winapi/src/shared/evntprov.rs | 1 - vendor/winapi/src/shared/evntrace.rs | 3 +- vendor/winapi/src/shared/guiddef.rs | 1 - vendor/winapi/src/shared/hidclass.rs | 1 - vendor/winapi/src/shared/hidpi.rs | 1 - vendor/winapi/src/shared/hidsdi.rs | 1 - vendor/winapi/src/shared/hidusage.rs | 1 - vendor/winapi/src/shared/ifdef.rs | 22 + vendor/winapi/src/shared/in6addr.rs | 1 - vendor/winapi/src/shared/inaddr.rs | 1 - vendor/winapi/src/shared/intsafe.rs | 1 - vendor/winapi/src/shared/ks.rs | 1 - vendor/winapi/src/shared/ksmedia.rs | 52 +- vendor/winapi/src/shared/ktmtypes.rs | 1 - vendor/winapi/src/shared/lmcons.rs | 1 - vendor/winapi/src/shared/minwindef.rs | 1 - vendor/winapi/src/shared/mmreg.rs | 1 - vendor/winapi/src/shared/mod.rs | 9 +- vendor/winapi/src/shared/mstcpip.rs | 6 +- vendor/winapi/src/shared/mswsockdef.rs | 48 + vendor/winapi/src/shared/netioapi.rs | 57 + vendor/winapi/src/shared/ntddscsi.rs | 1 - vendor/winapi/src/shared/ntddser.rs | 1 - vendor/winapi/src/shared/ntdef.rs | 1 - vendor/winapi/src/shared/ntstatus.rs | 1 - vendor/winapi/src/shared/qos.rs | 1 - vendor/winapi/src/shared/rpc.rs | 1 - vendor/winapi/src/shared/rpcdce.rs | 1 - vendor/winapi/src/shared/rpcndr.rs | 1 - vendor/winapi/src/shared/sddl.rs | 1 - vendor/winapi/src/shared/sspi.rs | 1 - vendor/winapi/src/shared/stralign.rs | 1 - .../src/shared/transportsettingcommon.rs | 1 - vendor/winapi/src/shared/tvout.rs | 1 - vendor/winapi/src/shared/usb.rs | 5 +- vendor/winapi/src/shared/usbiodef.rs | 1 - vendor/winapi/src/shared/usbspec.rs | 1 - vendor/winapi/src/shared/windef.rs | 10 +- vendor/winapi/src/shared/windowsx.rs | 1 - vendor/winapi/src/shared/winerror.rs | 58 +- vendor/winapi/src/shared/winusbio.rs | 1 - vendor/winapi/src/shared/wmistr.rs | 1 - vendor/winapi/src/shared/wnnc.rs | 1 - vendor/winapi/src/shared/ws2def.rs | 5 - vendor/winapi/src/shared/ws2ipdef.rs | 12 +- vendor/winapi/src/shared/wtypes.rs | 318 +- vendor/winapi/src/shared/wtypesbase.rs | 1 - vendor/winapi/src/um/accctrl.rs | 1 - vendor/winapi/src/um/aclapi.rs | 7 +- vendor/winapi/src/um/appmgmt.rs | 1 - vendor/winapi/src/um/audioclient.rs | 1 - vendor/winapi/src/um/audiosessiontypes.rs | 1 - vendor/winapi/src/um/avrt.rs | 1 - vendor/winapi/src/um/bits.rs | 3 +- vendor/winapi/src/um/bits10_1.rs | 1 - vendor/winapi/src/um/bits1_5.rs | 1 - vendor/winapi/src/um/bits2_0.rs | 1 - vendor/winapi/src/um/bits2_5.rs | 3 +- vendor/winapi/src/um/bits3_0.rs | 1 - vendor/winapi/src/um/bits4_0.rs | 1 - vendor/winapi/src/um/bits5_0.rs | 1 - vendor/winapi/src/um/bitscfg.rs | 1 - vendor/winapi/src/um/bitsmsg.rs | 1 - vendor/winapi/src/um/bluetoothapis.rs | 414 + vendor/winapi/src/um/bluetoothleapis.rs | 104 + vendor/winapi/src/um/bthledef.rs | 280 + vendor/winapi/src/um/cfgmgr32.rs | 38 +- vendor/winapi/src/um/cguid.rs | 1 - vendor/winapi/src/um/combaseapi.rs | 1 - vendor/winapi/src/um/coml2api.rs | 1 - vendor/winapi/src/um/commapi.rs | 37 +- vendor/winapi/src/um/commctrl.rs | 9 +- vendor/winapi/src/um/commdlg.rs | 1 - vendor/winapi/src/um/commoncontrols.rs | 1 - vendor/winapi/src/um/consoleapi.rs | 20 +- vendor/winapi/src/um/corsym.rs | 1 - vendor/winapi/src/um/d2d1.rs | 4 +- vendor/winapi/src/um/d2d1_1.rs | 13 +- vendor/winapi/src/um/d2d1_2.rs | 8 +- vendor/winapi/src/um/d2d1_3.rs | 10 +- vendor/winapi/src/um/d2d1effectauthor.rs | 13 +- vendor/winapi/src/um/d2d1effects.rs | 1 - vendor/winapi/src/um/d2d1effects_1.rs | 1 - vendor/winapi/src/um/d2d1effects_2.rs | 1 - vendor/winapi/src/um/d2d1svg.rs | 1 - vendor/winapi/src/um/d2dbasetypes.rs | 1 - vendor/winapi/src/um/d3d.rs | 1 - vendor/winapi/src/um/d3d10.rs | 1 - vendor/winapi/src/um/d3d10_1.rs | 1 - vendor/winapi/src/um/d3d10_1shader.rs | 1 - vendor/winapi/src/um/d3d10effect.rs | 1 - vendor/winapi/src/um/d3d10misc.rs | 1 - vendor/winapi/src/um/d3d10sdklayers.rs | 1 - vendor/winapi/src/um/d3d10shader.rs | 1 - vendor/winapi/src/um/d3d11.rs | 5 +- vendor/winapi/src/um/d3d11_1.rs | 4 +- vendor/winapi/src/um/d3d11_2.rs | 1 - vendor/winapi/src/um/d3d11_3.rs | 1 - vendor/winapi/src/um/d3d11_4.rs | 1 - vendor/winapi/src/um/d3d11on12.rs | 3 +- vendor/winapi/src/um/d3d11sdklayers.rs | 1 - vendor/winapi/src/um/d3d11shader.rs | 1 - .../src/um/d3d11tokenizedprogramformat.rs | 404 +- vendor/winapi/src/um/d3d12.rs | 9 +- vendor/winapi/src/um/d3d12sdklayers.rs | 4 +- vendor/winapi/src/um/d3d12shader.rs | 1 - vendor/winapi/src/um/d3dcommon.rs | 1 - vendor/winapi/src/um/d3dcompiler.rs | 1 - vendor/winapi/src/um/d3dcsx.rs | 1 - vendor/winapi/src/um/d3dx10core.rs | 1 - vendor/winapi/src/um/d3dx10math.rs | 1 - vendor/winapi/src/um/d3dx10mesh.rs | 1 - vendor/winapi/src/um/datetimeapi.rs | 1 - vendor/winapi/src/um/davclnt.rs | 1 - vendor/winapi/src/um/dbghelp.rs | 75 +- vendor/winapi/src/um/dbt.rs | 3 +- vendor/winapi/src/um/dcommon.rs | 1 - vendor/winapi/src/um/dcomp.rs | 16 +- vendor/winapi/src/um/dcompanimation.rs | 1 - vendor/winapi/src/um/dde.rs | 1 - vendor/winapi/src/um/ddraw.rs | 1 - vendor/winapi/src/um/ddrawi.rs | 1 - vendor/winapi/src/um/ddrawint.rs | 1 - vendor/winapi/src/um/debugapi.rs | 1 - vendor/winapi/src/um/devicetopology.rs | 3 +- vendor/winapi/src/um/dinput.rs | 1 - vendor/winapi/src/um/dispex.rs | 221 + vendor/winapi/src/um/dmksctl.rs | 1 - vendor/winapi/src/um/dmusicc.rs | 1 - vendor/winapi/src/um/docobj.rs | 1 - vendor/winapi/src/um/documenttarget.rs | 1 - vendor/winapi/src/um/dpa_dsa.rs | 1 - vendor/winapi/src/um/dpapi.rs | 1 - vendor/winapi/src/um/dsgetdc.rs | 1 - vendor/winapi/src/um/dsound.rs | 1 - vendor/winapi/src/um/dsrole.rs | 1 - vendor/winapi/src/um/dvp.rs | 1 - vendor/winapi/src/um/dwmapi.rs | 15 +- vendor/winapi/src/um/dwrite.rs | 1 - vendor/winapi/src/um/dwrite_1.rs | 1 - vendor/winapi/src/um/dwrite_2.rs | 1 - vendor/winapi/src/um/dwrite_3.rs | 1 - vendor/winapi/src/um/dxdiag.rs | 1 - vendor/winapi/src/um/dxfile.rs | 1 - vendor/winapi/src/um/dxgidebug.rs | 1 - vendor/winapi/src/um/dxva2api.rs | 1 - vendor/winapi/src/um/dxvahd.rs | 1 - vendor/winapi/src/um/enclaveapi.rs | 64 + vendor/winapi/src/um/endpointvolume.rs | 1 - vendor/winapi/src/um/errhandlingapi.rs | 1 - vendor/winapi/src/um/evntcons.rs | 6 +- vendor/winapi/src/um/exdisp.rs | 1 - vendor/winapi/src/um/fibersapi.rs | 1 - vendor/winapi/src/um/fileapi.rs | 75 +- .../src/um/functiondiscoverykeys_devpkey.rs | 117 + vendor/winapi/src/um/gl/gl.rs | 1 - vendor/winapi/src/um/gl/mod.rs | 1 - vendor/winapi/src/um/handleapi.rs | 1 - vendor/winapi/src/um/heapapi.rs | 1 - .../um/highlevelmonitorconfigurationapi.rs | 1 - vendor/winapi/src/um/http.rs | 5 +- vendor/winapi/src/um/imm.rs | 1 - vendor/winapi/src/um/interlockedapi.rs | 1 - vendor/winapi/src/um/ioapiset.rs | 1 - vendor/winapi/src/um/jobapi.rs | 1 - vendor/winapi/src/um/jobapi2.rs | 1 - vendor/winapi/src/um/knownfolders.rs | 1 - vendor/winapi/src/um/ktmw32.rs | 1 - vendor/winapi/src/um/libloaderapi.rs | 1 - vendor/winapi/src/um/lmaccess.rs | 1 - vendor/winapi/src/um/lmalert.rs | 1 - vendor/winapi/src/um/lmapibuf.rs | 1 - vendor/winapi/src/um/lmat.rs | 1 - vendor/winapi/src/um/lmdfs.rs | 11 +- vendor/winapi/src/um/lmerrlog.rs | 1 - vendor/winapi/src/um/lmjoin.rs | 1 - vendor/winapi/src/um/lmmsg.rs | 1 - vendor/winapi/src/um/lmremutl.rs | 1 - vendor/winapi/src/um/lmrepl.rs | 1 - vendor/winapi/src/um/lmserver.rs | 1 - vendor/winapi/src/um/lmshare.rs | 1 - vendor/winapi/src/um/lmstats.rs | 1 - vendor/winapi/src/um/lmsvc.rs | 1 - vendor/winapi/src/um/lmuse.rs | 1 - vendor/winapi/src/um/lmwksta.rs | 1 - .../src/um/lowlevelmonitorconfigurationapi.rs | 1 - vendor/winapi/src/um/lsalookup.rs | 1 - vendor/winapi/src/um/memoryapi.rs | 1 - vendor/winapi/src/um/minschannel.rs | 1 - vendor/winapi/src/um/minwinbase.rs | 5 +- vendor/winapi/src/um/mmdeviceapi.rs | 3 +- vendor/winapi/src/um/mmeapi.rs | 1 - vendor/winapi/src/um/mmsystem.rs | 1 - vendor/winapi/src/um/mod.rs | 22 +- vendor/winapi/src/um/msaatext.rs | 1 - vendor/winapi/src/um/mscat.rs | 1 - vendor/winapi/src/um/mschapp.rs | 1 - vendor/winapi/src/um/mssip.rs | 1 - vendor/winapi/src/um/mswsock.rs | 413 + vendor/winapi/src/um/namedpipeapi.rs | 1 - vendor/winapi/src/um/namespaceapi.rs | 1 - vendor/winapi/src/um/nb30.rs | 5 +- vendor/winapi/src/um/ncrypt.rs | 1 - vendor/winapi/src/um/ntlsa.rs | 25 +- vendor/winapi/src/um/ntsecapi.rs | 5 +- vendor/winapi/src/um/oaidl.rs | 79 +- vendor/winapi/src/um/objbase.rs | 1 - vendor/winapi/src/um/objidl.rs | 1 - vendor/winapi/src/um/objidlbase.rs | 13 +- vendor/winapi/src/um/ocidl.rs | 1 - vendor/winapi/src/um/ole2.rs | 3 +- vendor/winapi/src/um/oleauto.rs | 14 +- vendor/winapi/src/um/olectl.rs | 1 - vendor/winapi/src/um/oleidl.rs | 1 - vendor/winapi/src/um/opmapi.rs | 1 - vendor/winapi/src/um/pdh.rs | 1 - vendor/winapi/src/um/perflib.rs | 1 - .../src/um/physicalmonitorenumerationapi.rs | 1 - vendor/winapi/src/um/playsoundapi.rs | 1 - vendor/winapi/src/um/portabledevice.rs | 163 + vendor/winapi/src/um/portabledeviceapi.rs | 288 + vendor/winapi/src/um/portabledevicetypes.rs | 255 + vendor/winapi/src/um/powerbase.rs | 1 - vendor/winapi/src/um/powersetting.rs | 1 - vendor/winapi/src/um/powrprof.rs | 1 - vendor/winapi/src/um/processenv.rs | 1 - vendor/winapi/src/um/processsnapshot.rs | 11 +- vendor/winapi/src/um/processthreadsapi.rs | 1 - vendor/winapi/src/um/processtopologyapi.rs | 1 - vendor/winapi/src/um/profileapi.rs | 1 - vendor/winapi/src/um/propidl.rs | 384 +- vendor/winapi/src/um/propkey.rs | 2300 +++ vendor/winapi/src/um/propkeydef.rs | 1 - vendor/winapi/src/um/propsys.rs | 9 +- vendor/winapi/src/um/prsht.rs | 1 - vendor/winapi/src/um/psapi.rs | 125 +- vendor/winapi/src/um/realtimeapiset.rs | 1 - vendor/winapi/src/um/reason.rs | 1 - vendor/winapi/src/um/restartmanager.rs | 1 - vendor/winapi/src/um/restrictederrorinfo.rs | 1 - vendor/winapi/src/um/rmxfguid.rs | 1 - vendor/winapi/src/um/sapi.rs | 1 - vendor/winapi/src/um/sapi51.rs | 7 +- vendor/winapi/src/um/sapi53.rs | 1 - vendor/winapi/src/um/sapiddk.rs | 1 - vendor/winapi/src/um/sapiddk51.rs | 1 - vendor/winapi/src/um/schannel.rs | 1 - vendor/winapi/src/um/securityappcontainer.rs | 1 - vendor/winapi/src/um/securitybaseapi.rs | 5 +- vendor/winapi/src/um/servprov.rs | 1 - vendor/winapi/src/um/setupapi.rs | 4 +- vendor/winapi/src/um/shellapi.rs | 1 - vendor/winapi/src/um/shellscalingapi.rs | 1 - vendor/winapi/src/um/shlobj.rs | 1 - vendor/winapi/src/um/shobjidl.rs | 1 - vendor/winapi/src/um/shobjidl_core.rs | 222 +- vendor/winapi/src/um/shtypes.rs | 1 - vendor/winapi/src/um/spapidef.rs | 1 - vendor/winapi/src/um/spellcheck.rs | 146 + vendor/winapi/src/um/sporder.rs | 5 +- vendor/winapi/src/um/sql.rs | 1 - vendor/winapi/src/um/sqlext.rs | 3 +- vendor/winapi/src/um/sqltypes.rs | 17 +- vendor/winapi/src/um/sqlucode.rs | 1 - vendor/winapi/src/um/sspi.rs | 1 - vendor/winapi/src/um/stringapiset.rs | 1 - vendor/winapi/src/um/strmif.rs | 1 - vendor/winapi/src/um/subauth.rs | 1 - vendor/winapi/src/um/synchapi.rs | 3 +- vendor/winapi/src/um/sysinfoapi.rs | 1 - vendor/winapi/src/um/systemtopologyapi.rs | 3 +- vendor/winapi/src/um/taskschd.rs | 1233 ++ vendor/winapi/src/um/textstor.rs | 1 - vendor/winapi/src/um/threadpoolapiset.rs | 1 - .../winapi/src/um/threadpoollegacyapiset.rs | 1 - vendor/winapi/src/um/timeapi.rs | 1 - vendor/winapi/src/um/timezoneapi.rs | 1 - vendor/winapi/src/um/tlhelp32.rs | 1 - vendor/winapi/src/um/unknwnbase.rs | 1 - vendor/winapi/src/um/urlhist.rs | 1 - vendor/winapi/src/um/urlmon.rs | 1 - vendor/winapi/src/um/userenv.rs | 13 +- vendor/winapi/src/um/usp10.rs | 23 +- vendor/winapi/src/um/utilapiset.rs | 1 - vendor/winapi/src/um/uxtheme.rs | 1 - vendor/winapi/src/um/vsbackup.rs | 1 - vendor/winapi/src/um/vss.rs | 1 - vendor/winapi/src/um/vsserror.rs | 1 - vendor/winapi/src/um/vswriter.rs | 1 - vendor/winapi/src/um/wbemads.rs | 41 + vendor/winapi/src/um/wbemcli.rs | 1174 ++ vendor/winapi/src/um/wbemdisp.rs | 1344 ++ vendor/winapi/src/um/wbemprov.rs | 302 + vendor/winapi/src/um/wbemtran.rs | 184 + vendor/winapi/src/um/wct.rs | 1 - vendor/winapi/src/um/werapi.rs | 15 +- vendor/winapi/src/um/winbase.rs | 505 +- vendor/winapi/src/um/wincodec.rs | 12 +- vendor/winapi/src/um/wincodecsdk.rs | 1 - vendor/winapi/src/um/wincon.rs | 129 +- vendor/winapi/src/um/wincontypes.rs | 114 + vendor/winapi/src/um/wincred.rs | 1 - vendor/winapi/src/um/wincrypt.rs | 17 +- vendor/winapi/src/um/windowsceip.rs | 1 - vendor/winapi/src/um/winefs.rs | 1 - vendor/winapi/src/um/winevt.rs | 1 - vendor/winapi/src/um/wingdi.rs | 46 +- vendor/winapi/src/um/winhttp.rs | 3 +- vendor/winapi/src/um/wininet.rs | 1 - vendor/winapi/src/um/winineti.rs | 1 - vendor/winapi/src/um/winioctl.rs | 184 +- vendor/winapi/src/um/winnetwk.rs | 1 - vendor/winapi/src/um/winnls.rs | 1 - vendor/winapi/src/um/winnt.rs | 323 +- vendor/winapi/src/um/winreg.rs | 51 +- vendor/winapi/src/um/winsafer.rs | 1 - vendor/winapi/src/um/winscard.rs | 1 - vendor/winapi/src/um/winsmcrd.rs | 1 - vendor/winapi/src/um/winsock2.rs | 9 +- vendor/winapi/src/um/winspool.rs | 1 - vendor/winapi/src/um/winsvc.rs | 1 - vendor/winapi/src/um/winusb.rs | 1 - vendor/winapi/src/um/winuser.rs | 1230 +- vendor/winapi/src/um/winver.rs | 1 - vendor/winapi/src/um/wow64apiset.rs | 1 - vendor/winapi/src/um/wpdmtpextensions.rs | 60 + vendor/winapi/src/um/ws2bth.rs | 211 + vendor/winapi/src/um/ws2spi.rs | 35 +- vendor/winapi/src/um/ws2tcpip.rs | 1 - vendor/winapi/src/um/xinput.rs | 1 - vendor/winapi/src/vc/excpt.rs | 1 - vendor/winapi/src/vc/limits.rs | 1 - vendor/winapi/src/vc/mod.rs | 1 - vendor/winapi/src/vc/vadefs.rs | 1 - vendor/winapi/src/vc/vcruntime.rs | 1 - vendor/winapi/src/winrt/activation.rs | 1 - vendor/winapi/src/winrt/hstring.rs | 5 +- vendor/winapi/src/winrt/inspectable.rs | 1 - vendor/winapi/src/winrt/mod.rs | 1 - vendor/winapi/src/winrt/roapi.rs | 1 - vendor/winapi/src/winrt/robuffer.rs | 3 +- vendor/winapi/src/winrt/roerrorapi.rs | 1 - vendor/winapi/src/winrt/winstring.rs | 3 +- version | 2 +- 5444 files changed, 168239 insertions(+), 77148 deletions(-) create mode 100755 src/ci/docker/mingw-check/validate-toolstate.sh rename src/ci/docker/{x86_64-gnu-llvm-6.0 => x86_64-gnu-llvm-7}/Dockerfile (90%) delete mode 100755 src/ci/docker/x86_64-gnu-tools/checkregression.py delete mode 100644 src/ci/docker/x86_64-gnu-tools/repo.sh create mode 100755 src/ci/publish_toolstate.sh create mode 100755 src/ci/scripts/clean-disk.sh create mode 100755 src/ci/scripts/collect-cpu-stats.sh create mode 100755 src/ci/scripts/run-build-from-ci.sh create mode 100755 src/ci/scripts/setup-environment.sh create mode 100644 src/doc/edition-guide/.github/workflows/main.yml delete mode 100644 src/doc/edition-guide/.travis.yml create mode 100644 src/doc/nomicon/.github/workflows/main.yml delete mode 100644 src/doc/nomicon/.travis.yml create mode 100644 src/doc/reference/.github/workflows/main.yml delete mode 100644 src/doc/reference/.travis.yml delete mode 100755 src/doc/rustc-guide/ci/build-ignore-timeouts.sh create mode 100644 src/doc/rustc-guide/src/appendix/compiler-lecture.md create mode 100644 src/doc/rustc-guide/src/building/bootstrapping.md rename src/doc/rustc-guide/src/{ => building}/build-install-distribution-artifacts.md (100%) create mode 100644 src/doc/rustc-guide/src/building/compiler-documenting.md create mode 100644 src/doc/rustc-guide/src/building/ctags.md create mode 100644 src/doc/rustc-guide/src/building/how-to-build-and-run.md create mode 100644 src/doc/rustc-guide/src/building/suggested.md create mode 100644 src/doc/rustc-guide/src/codegen/backend-agnostic.md delete mode 100644 src/doc/rustc-guide/src/compiler-documenting.md delete mode 100644 src/doc/rustc-guide/src/diagnostics/json-format.md create mode 100644 src/doc/rustc-guide/src/diagnostics/lintstore.md create mode 100644 src/doc/rustc-guide/src/generic_arguments.md delete mode 100644 src/doc/rustc-guide/src/how-to-build-and-run.md create mode 100644 src/doc/rustc-guide/src/ice-breaker/about.md create mode 100644 src/doc/rustc-guide/src/ice-breaker/llvm.md delete mode 100644 src/doc/rustc-guide/src/important-links.md delete mode 100644 src/doc/rustc-guide/src/kinds.md create mode 100644 src/doc/rustc-guide/src/salsa.md create mode 100644 src/doc/rustc-guide/src/sanitizers.md create mode 100644 src/doc/rustdoc/src/advanced-features.md create mode 100644 src/doc/rustdoc/src/how-to-write-documentation.md create mode 100644 src/doc/rustdoc/src/lints.md create mode 100644 src/doc/unstable-book/src/language-features/cfg-sanitize.md create mode 100644 src/doc/unstable-book/src/language-features/const-if-match.md delete mode 100644 src/doc/unstable-book/src/language-features/on-unimplemented.md delete mode 100644 src/doc/unstable-book/src/language-features/re-rebalance-coherence.md mode change 100644 => 100755 src/etc/dec2flt_table.py create mode 100644 src/etc/natvis/libstd.natvis create mode 100644 src/libcore/benches/pattern.rs rename src/libcore/{convert.rs => convert/mod.rs} (92%) create mode 100644 src/libcore/convert/num.rs rename src/libcore/{macros.rs => macros/mod.rs} (88%) create mode 100644 src/libcore/macros/panic.md mode change 100644 => 100755 src/libcore/unicode/printable.py delete mode 100644 src/librustc/benches/dispatch.rs delete mode 100644 src/librustc/benches/pattern.rs delete mode 100644 src/librustc/error_codes.rs delete mode 100644 src/librustc/ich/impls_misc.rs delete mode 100644 src/librustc/middle/mem_categorization.rs create mode 100644 src/librustc/ty/diagnostics.rs delete mode 100644 src/librustc_codegen_ssa/error_codes.rs rename src/{librustc/util => librustc_data_structures}/profiling.rs (88%) create mode 100644 src/librustc_error_codes/Cargo.toml create mode 100644 src/librustc_error_codes/error_codes.rs create mode 100644 src/librustc_error_codes/error_codes/E0001.md create mode 100644 src/librustc_error_codes/error_codes/E0002.md create mode 100644 src/librustc_error_codes/error_codes/E0004.md create mode 100644 src/librustc_error_codes/error_codes/E0005.md create mode 100644 src/librustc_error_codes/error_codes/E0007.md create mode 100644 src/librustc_error_codes/error_codes/E0009.md create mode 100644 src/librustc_error_codes/error_codes/E0010.md create mode 100644 src/librustc_error_codes/error_codes/E0013.md create mode 100644 src/librustc_error_codes/error_codes/E0014.md create mode 100644 src/librustc_error_codes/error_codes/E0015.md create mode 100644 src/librustc_error_codes/error_codes/E0019.md create mode 100644 src/librustc_error_codes/error_codes/E0023.md create mode 100644 src/librustc_error_codes/error_codes/E0025.md create mode 100644 src/librustc_error_codes/error_codes/E0026.md create mode 100644 src/librustc_error_codes/error_codes/E0027.md create mode 100644 src/librustc_error_codes/error_codes/E0029.md create mode 100644 src/librustc_error_codes/error_codes/E0030.md create mode 100644 src/librustc_error_codes/error_codes/E0033.md create mode 100644 src/librustc_error_codes/error_codes/E0034.md create mode 100644 src/librustc_error_codes/error_codes/E0038.md create mode 100644 src/librustc_error_codes/error_codes/E0040.md create mode 100644 src/librustc_error_codes/error_codes/E0044.md create mode 100644 src/librustc_error_codes/error_codes/E0045.md create mode 100644 src/librustc_error_codes/error_codes/E0046.md create mode 100644 src/librustc_error_codes/error_codes/E0049.md create mode 100644 src/librustc_error_codes/error_codes/E0050.md create mode 100644 src/librustc_error_codes/error_codes/E0053.md create mode 100644 src/librustc_error_codes/error_codes/E0054.md create mode 100644 src/librustc_error_codes/error_codes/E0055.md create mode 100644 src/librustc_error_codes/error_codes/E0057.md create mode 100644 src/librustc_error_codes/error_codes/E0059.md create mode 100644 src/librustc_error_codes/error_codes/E0060.md create mode 100644 src/librustc_error_codes/error_codes/E0061.md create mode 100644 src/librustc_error_codes/error_codes/E0062.md create mode 100644 src/librustc_error_codes/error_codes/E0063.md create mode 100644 src/librustc_error_codes/error_codes/E0067.md create mode 100644 src/librustc_error_codes/error_codes/E0069.md create mode 100644 src/librustc_error_codes/error_codes/E0070.md create mode 100644 src/librustc_error_codes/error_codes/E0071.md create mode 100644 src/librustc_error_codes/error_codes/E0072.md create mode 100644 src/librustc_error_codes/error_codes/E0073.md create mode 100644 src/librustc_error_codes/error_codes/E0074.md create mode 100644 src/librustc_error_codes/error_codes/E0075.md create mode 100644 src/librustc_error_codes/error_codes/E0076.md create mode 100644 src/librustc_error_codes/error_codes/E0077.md create mode 100644 src/librustc_error_codes/error_codes/E0080.md create mode 100644 src/librustc_error_codes/error_codes/E0081.md create mode 100644 src/librustc_error_codes/error_codes/E0084.md create mode 100644 src/librustc_error_codes/error_codes/E0087.md create mode 100644 src/librustc_error_codes/error_codes/E0088.md create mode 100644 src/librustc_error_codes/error_codes/E0089.md create mode 100644 src/librustc_error_codes/error_codes/E0090.md create mode 100644 src/librustc_error_codes/error_codes/E0091.md create mode 100644 src/librustc_error_codes/error_codes/E0092.md create mode 100644 src/librustc_error_codes/error_codes/E0093.md create mode 100644 src/librustc_error_codes/error_codes/E0094.md create mode 100644 src/librustc_error_codes/error_codes/E0106.md create mode 100644 src/librustc_error_codes/error_codes/E0107.md create mode 100644 src/librustc_error_codes/error_codes/E0109.md create mode 100644 src/librustc_error_codes/error_codes/E0110.md create mode 100644 src/librustc_error_codes/error_codes/E0116.md create mode 100644 src/librustc_error_codes/error_codes/E0117.md create mode 100644 src/librustc_error_codes/error_codes/E0118.md create mode 100644 src/librustc_error_codes/error_codes/E0119.md create mode 100644 src/librustc_error_codes/error_codes/E0120.md create mode 100644 src/librustc_error_codes/error_codes/E0121.md create mode 100644 src/librustc_error_codes/error_codes/E0124.md create mode 100644 src/librustc_error_codes/error_codes/E0128.md create mode 100644 src/librustc_error_codes/error_codes/E0130.md create mode 100644 src/librustc_error_codes/error_codes/E0131.md create mode 100644 src/librustc_error_codes/error_codes/E0132.md create mode 100644 src/librustc_error_codes/error_codes/E0133.md create mode 100644 src/librustc_error_codes/error_codes/E0136.md create mode 100644 src/librustc_error_codes/error_codes/E0137.md create mode 100644 src/librustc_error_codes/error_codes/E0138.md create mode 100644 src/librustc_error_codes/error_codes/E0139.md create mode 100644 src/librustc_error_codes/error_codes/E0152.md create mode 100644 src/librustc_error_codes/error_codes/E0154.md create mode 100644 src/librustc_error_codes/error_codes/E0158.md create mode 100644 src/librustc_error_codes/error_codes/E0161.md create mode 100644 src/librustc_error_codes/error_codes/E0162.md create mode 100644 src/librustc_error_codes/error_codes/E0164.md create mode 100644 src/librustc_error_codes/error_codes/E0165.md create mode 100644 src/librustc_error_codes/error_codes/E0170.md create mode 100644 src/librustc_error_codes/error_codes/E0178.md create mode 100644 src/librustc_error_codes/error_codes/E0184.md create mode 100644 src/librustc_error_codes/error_codes/E0185.md create mode 100644 src/librustc_error_codes/error_codes/E0186.md create mode 100644 src/librustc_error_codes/error_codes/E0191.md create mode 100644 src/librustc_error_codes/error_codes/E0192.md create mode 100644 src/librustc_error_codes/error_codes/E0193.md create mode 100644 src/librustc_error_codes/error_codes/E0195.md create mode 100644 src/librustc_error_codes/error_codes/E0197.md create mode 100644 src/librustc_error_codes/error_codes/E0198.md create mode 100644 src/librustc_error_codes/error_codes/E0199.md create mode 100644 src/librustc_error_codes/error_codes/E0200.md create mode 100644 src/librustc_error_codes/error_codes/E0201.md create mode 100644 src/librustc_error_codes/error_codes/E0202.md create mode 100644 src/librustc_error_codes/error_codes/E0203.md create mode 100644 src/librustc_error_codes/error_codes/E0204.md create mode 100644 src/librustc_error_codes/error_codes/E0205.md create mode 100644 src/librustc_error_codes/error_codes/E0206.md create mode 100644 src/librustc_error_codes/error_codes/E0207.md create mode 100644 src/librustc_error_codes/error_codes/E0210.md create mode 100644 src/librustc_error_codes/error_codes/E0211.md create mode 100644 src/librustc_error_codes/error_codes/E0214.md create mode 100644 src/librustc_error_codes/error_codes/E0220.md create mode 100644 src/librustc_error_codes/error_codes/E0221.md create mode 100644 src/librustc_error_codes/error_codes/E0223.md create mode 100644 src/librustc_error_codes/error_codes/E0225.md create mode 100644 src/librustc_error_codes/error_codes/E0229.md create mode 100644 src/librustc_error_codes/error_codes/E0230.md create mode 100644 src/librustc_error_codes/error_codes/E0231.md create mode 100644 src/librustc_error_codes/error_codes/E0232.md create mode 100644 src/librustc_error_codes/error_codes/E0243.md create mode 100644 src/librustc_error_codes/error_codes/E0244.md create mode 100644 src/librustc_error_codes/error_codes/E0251.md create mode 100644 src/librustc_error_codes/error_codes/E0252.md create mode 100644 src/librustc_error_codes/error_codes/E0253.md create mode 100644 src/librustc_error_codes/error_codes/E0254.md create mode 100644 src/librustc_error_codes/error_codes/E0255.md create mode 100644 src/librustc_error_codes/error_codes/E0256.md create mode 100644 src/librustc_error_codes/error_codes/E0259.md create mode 100644 src/librustc_error_codes/error_codes/E0260.md create mode 100644 src/librustc_error_codes/error_codes/E0261.md create mode 100644 src/librustc_error_codes/error_codes/E0262.md create mode 100644 src/librustc_error_codes/error_codes/E0263.md create mode 100644 src/librustc_error_codes/error_codes/E0264.md create mode 100644 src/librustc_error_codes/error_codes/E0267.md create mode 100644 src/librustc_error_codes/error_codes/E0268.md create mode 100644 src/librustc_error_codes/error_codes/E0271.md create mode 100644 src/librustc_error_codes/error_codes/E0275.md create mode 100644 src/librustc_error_codes/error_codes/E0276.md create mode 100644 src/librustc_error_codes/error_codes/E0277.md create mode 100644 src/librustc_error_codes/error_codes/E0281.md create mode 100644 src/librustc_error_codes/error_codes/E0282.md create mode 100644 src/librustc_error_codes/error_codes/E0283.md create mode 100644 src/librustc_error_codes/error_codes/E0284.md create mode 100644 src/librustc_error_codes/error_codes/E0297.md create mode 100644 src/librustc_error_codes/error_codes/E0301.md create mode 100644 src/librustc_error_codes/error_codes/E0302.md create mode 100644 src/librustc_error_codes/error_codes/E0303.md create mode 100644 src/librustc_error_codes/error_codes/E0307.md create mode 100644 src/librustc_error_codes/error_codes/E0308.md create mode 100644 src/librustc_error_codes/error_codes/E0309.md create mode 100644 src/librustc_error_codes/error_codes/E0310.md create mode 100644 src/librustc_error_codes/error_codes/E0312.md create mode 100644 src/librustc_error_codes/error_codes/E0317.md create mode 100644 src/librustc_error_codes/error_codes/E0321.md create mode 100644 src/librustc_error_codes/error_codes/E0322.md create mode 100644 src/librustc_error_codes/error_codes/E0323.md create mode 100644 src/librustc_error_codes/error_codes/E0324.md create mode 100644 src/librustc_error_codes/error_codes/E0325.md create mode 100644 src/librustc_error_codes/error_codes/E0326.md create mode 100644 src/librustc_error_codes/error_codes/E0328.md create mode 100644 src/librustc_error_codes/error_codes/E0329.md create mode 100644 src/librustc_error_codes/error_codes/E0364.md create mode 100644 src/librustc_error_codes/error_codes/E0365.md create mode 100644 src/librustc_error_codes/error_codes/E0366.md create mode 100644 src/librustc_error_codes/error_codes/E0367.md create mode 100644 src/librustc_error_codes/error_codes/E0368.md create mode 100644 src/librustc_error_codes/error_codes/E0369.md create mode 100644 src/librustc_error_codes/error_codes/E0370.md create mode 100644 src/librustc_error_codes/error_codes/E0371.md create mode 100644 src/librustc_error_codes/error_codes/E0373.md create mode 100644 src/librustc_error_codes/error_codes/E0374.md create mode 100644 src/librustc_error_codes/error_codes/E0375.md create mode 100644 src/librustc_error_codes/error_codes/E0376.md create mode 100644 src/librustc_error_codes/error_codes/E0378.md create mode 100644 src/librustc_error_codes/error_codes/E0379.md create mode 100644 src/librustc_error_codes/error_codes/E0380.md create mode 100644 src/librustc_error_codes/error_codes/E0381.md create mode 100644 src/librustc_error_codes/error_codes/E0382.md create mode 100644 src/librustc_error_codes/error_codes/E0383.md create mode 100644 src/librustc_error_codes/error_codes/E0384.md create mode 100644 src/librustc_error_codes/error_codes/E0386.md create mode 100644 src/librustc_error_codes/error_codes/E0387.md create mode 100644 src/librustc_error_codes/error_codes/E0388.md create mode 100644 src/librustc_error_codes/error_codes/E0389.md create mode 100644 src/librustc_error_codes/error_codes/E0390.md create mode 100644 src/librustc_error_codes/error_codes/E0391.md create mode 100644 src/librustc_error_codes/error_codes/E0392.md create mode 100644 src/librustc_error_codes/error_codes/E0393.md create mode 100644 src/librustc_error_codes/error_codes/E0398.md create mode 100644 src/librustc_error_codes/error_codes/E0399.md create mode 100644 src/librustc_error_codes/error_codes/E0401.md create mode 100644 src/librustc_error_codes/error_codes/E0403.md create mode 100644 src/librustc_error_codes/error_codes/E0404.md create mode 100644 src/librustc_error_codes/error_codes/E0405.md create mode 100644 src/librustc_error_codes/error_codes/E0407.md create mode 100644 src/librustc_error_codes/error_codes/E0408.md create mode 100644 src/librustc_error_codes/error_codes/E0409.md create mode 100644 src/librustc_error_codes/error_codes/E0411.md create mode 100644 src/librustc_error_codes/error_codes/E0412.md create mode 100644 src/librustc_error_codes/error_codes/E0415.md create mode 100644 src/librustc_error_codes/error_codes/E0416.md create mode 100644 src/librustc_error_codes/error_codes/E0422.md create mode 100644 src/librustc_error_codes/error_codes/E0423.md create mode 100644 src/librustc_error_codes/error_codes/E0424.md create mode 100644 src/librustc_error_codes/error_codes/E0425.md create mode 100644 src/librustc_error_codes/error_codes/E0426.md create mode 100644 src/librustc_error_codes/error_codes/E0428.md create mode 100644 src/librustc_error_codes/error_codes/E0429.md create mode 100644 src/librustc_error_codes/error_codes/E0430.md create mode 100644 src/librustc_error_codes/error_codes/E0431.md create mode 100644 src/librustc_error_codes/error_codes/E0432.md create mode 100644 src/librustc_error_codes/error_codes/E0433.md create mode 100644 src/librustc_error_codes/error_codes/E0434.md create mode 100644 src/librustc_error_codes/error_codes/E0435.md create mode 100644 src/librustc_error_codes/error_codes/E0436.md create mode 100644 src/librustc_error_codes/error_codes/E0437.md create mode 100644 src/librustc_error_codes/error_codes/E0438.md create mode 100644 src/librustc_error_codes/error_codes/E0439.md create mode 100644 src/librustc_error_codes/error_codes/E0445.md create mode 100644 src/librustc_error_codes/error_codes/E0446.md create mode 100644 src/librustc_error_codes/error_codes/E0447.md create mode 100644 src/librustc_error_codes/error_codes/E0448.md create mode 100644 src/librustc_error_codes/error_codes/E0449.md create mode 100644 src/librustc_error_codes/error_codes/E0451.md create mode 100644 src/librustc_error_codes/error_codes/E0452.md create mode 100644 src/librustc_error_codes/error_codes/E0453.md create mode 100644 src/librustc_error_codes/error_codes/E0454.md create mode 100644 src/librustc_error_codes/error_codes/E0455.md create mode 100644 src/librustc_error_codes/error_codes/E0458.md create mode 100644 src/librustc_error_codes/error_codes/E0459.md create mode 100644 src/librustc_error_codes/error_codes/E0463.md create mode 100644 src/librustc_error_codes/error_codes/E0466.md create mode 100644 src/librustc_error_codes/error_codes/E0468.md create mode 100644 src/librustc_error_codes/error_codes/E0469.md create mode 100644 src/librustc_error_codes/error_codes/E0478.md create mode 100644 src/librustc_error_codes/error_codes/E0491.md create mode 100644 src/librustc_error_codes/error_codes/E0492.md create mode 100644 src/librustc_error_codes/error_codes/E0493.md create mode 100644 src/librustc_error_codes/error_codes/E0495.md create mode 100644 src/librustc_error_codes/error_codes/E0496.md create mode 100644 src/librustc_error_codes/error_codes/E0497.md create mode 100644 src/librustc_error_codes/error_codes/E0499.md create mode 100644 src/librustc_error_codes/error_codes/E0500.md create mode 100644 src/librustc_error_codes/error_codes/E0501.md create mode 100644 src/librustc_error_codes/error_codes/E0502.md create mode 100644 src/librustc_error_codes/error_codes/E0503.md create mode 100644 src/librustc_error_codes/error_codes/E0504.md create mode 100644 src/librustc_error_codes/error_codes/E0505.md create mode 100644 src/librustc_error_codes/error_codes/E0506.md create mode 100644 src/librustc_error_codes/error_codes/E0507.md create mode 100644 src/librustc_error_codes/error_codes/E0508.md create mode 100644 src/librustc_error_codes/error_codes/E0509.md create mode 100644 src/librustc_error_codes/error_codes/E0510.md create mode 100644 src/librustc_error_codes/error_codes/E0511.md create mode 100644 src/librustc_error_codes/error_codes/E0512.md create mode 100644 src/librustc_error_codes/error_codes/E0515.md create mode 100644 src/librustc_error_codes/error_codes/E0516.md create mode 100644 src/librustc_error_codes/error_codes/E0517.md create mode 100644 src/librustc_error_codes/error_codes/E0518.md create mode 100644 src/librustc_error_codes/error_codes/E0520.md create mode 100644 src/librustc_error_codes/error_codes/E0522.md create mode 100644 src/librustc_error_codes/error_codes/E0524.md create mode 100644 src/librustc_error_codes/error_codes/E0525.md create mode 100644 src/librustc_error_codes/error_codes/E0527.md create mode 100644 src/librustc_error_codes/error_codes/E0528.md create mode 100644 src/librustc_error_codes/error_codes/E0529.md create mode 100644 src/librustc_error_codes/error_codes/E0530.md create mode 100644 src/librustc_error_codes/error_codes/E0531.md create mode 100644 src/librustc_error_codes/error_codes/E0532.md create mode 100644 src/librustc_error_codes/error_codes/E0533.md create mode 100644 src/librustc_error_codes/error_codes/E0534.md create mode 100644 src/librustc_error_codes/error_codes/E0535.md create mode 100644 src/librustc_error_codes/error_codes/E0536.md create mode 100644 src/librustc_error_codes/error_codes/E0537.md create mode 100644 src/librustc_error_codes/error_codes/E0538.md create mode 100644 src/librustc_error_codes/error_codes/E0541.md create mode 100644 src/librustc_error_codes/error_codes/E0550.md create mode 100644 src/librustc_error_codes/error_codes/E0551.md create mode 100644 src/librustc_error_codes/error_codes/E0552.md create mode 100644 src/librustc_error_codes/error_codes/E0554.md create mode 100644 src/librustc_error_codes/error_codes/E0556.md create mode 100644 src/librustc_error_codes/error_codes/E0557.md create mode 100644 src/librustc_error_codes/error_codes/E0559.md create mode 100644 src/librustc_error_codes/error_codes/E0560.md create mode 100644 src/librustc_error_codes/error_codes/E0561.md create mode 100644 src/librustc_error_codes/error_codes/E0562.md create mode 100644 src/librustc_error_codes/error_codes/E0565.md create mode 100644 src/librustc_error_codes/error_codes/E0566.md create mode 100644 src/librustc_error_codes/error_codes/E0567.md create mode 100644 src/librustc_error_codes/error_codes/E0568.md create mode 100644 src/librustc_error_codes/error_codes/E0569.md create mode 100644 src/librustc_error_codes/error_codes/E0570.md create mode 100644 src/librustc_error_codes/error_codes/E0571.md create mode 100644 src/librustc_error_codes/error_codes/E0572.md create mode 100644 src/librustc_error_codes/error_codes/E0573.md create mode 100644 src/librustc_error_codes/error_codes/E0574.md create mode 100644 src/librustc_error_codes/error_codes/E0575.md create mode 100644 src/librustc_error_codes/error_codes/E0576.md create mode 100644 src/librustc_error_codes/error_codes/E0577.md create mode 100644 src/librustc_error_codes/error_codes/E0578.md create mode 100644 src/librustc_error_codes/error_codes/E0579.md create mode 100644 src/librustc_error_codes/error_codes/E0580.md create mode 100644 src/librustc_error_codes/error_codes/E0581.md create mode 100644 src/librustc_error_codes/error_codes/E0582.md create mode 100644 src/librustc_error_codes/error_codes/E0583.md create mode 100644 src/librustc_error_codes/error_codes/E0584.md create mode 100644 src/librustc_error_codes/error_codes/E0585.md create mode 100644 src/librustc_error_codes/error_codes/E0586.md create mode 100644 src/librustc_error_codes/error_codes/E0587.md create mode 100644 src/librustc_error_codes/error_codes/E0588.md create mode 100644 src/librustc_error_codes/error_codes/E0589.md create mode 100644 src/librustc_error_codes/error_codes/E0590.md create mode 100644 src/librustc_error_codes/error_codes/E0591.md create mode 100644 src/librustc_error_codes/error_codes/E0592.md create mode 100644 src/librustc_error_codes/error_codes/E0593.md create mode 100644 src/librustc_error_codes/error_codes/E0594.md create mode 100644 src/librustc_error_codes/error_codes/E0595.md create mode 100644 src/librustc_error_codes/error_codes/E0596.md create mode 100644 src/librustc_error_codes/error_codes/E0597.md create mode 100644 src/librustc_error_codes/error_codes/E0599.md create mode 100644 src/librustc_error_codes/error_codes/E0600.md create mode 100644 src/librustc_error_codes/error_codes/E0601.md create mode 100644 src/librustc_error_codes/error_codes/E0602.md create mode 100644 src/librustc_error_codes/error_codes/E0603.md create mode 100644 src/librustc_error_codes/error_codes/E0604.md create mode 100644 src/librustc_error_codes/error_codes/E0605.md create mode 100644 src/librustc_error_codes/error_codes/E0606.md create mode 100644 src/librustc_error_codes/error_codes/E0607.md create mode 100644 src/librustc_error_codes/error_codes/E0608.md create mode 100644 src/librustc_error_codes/error_codes/E0609.md create mode 100644 src/librustc_error_codes/error_codes/E0610.md create mode 100644 src/librustc_error_codes/error_codes/E0614.md create mode 100644 src/librustc_error_codes/error_codes/E0615.md create mode 100644 src/librustc_error_codes/error_codes/E0616.md create mode 100644 src/librustc_error_codes/error_codes/E0617.md create mode 100644 src/librustc_error_codes/error_codes/E0618.md create mode 100644 src/librustc_error_codes/error_codes/E0619.md create mode 100644 src/librustc_error_codes/error_codes/E0620.md create mode 100644 src/librustc_error_codes/error_codes/E0621.md create mode 100644 src/librustc_error_codes/error_codes/E0622.md create mode 100644 src/librustc_error_codes/error_codes/E0623.md create mode 100644 src/librustc_error_codes/error_codes/E0624.md create mode 100644 src/librustc_error_codes/error_codes/E0626.md create mode 100644 src/librustc_error_codes/error_codes/E0631.md create mode 100644 src/librustc_error_codes/error_codes/E0633.md create mode 100644 src/librustc_error_codes/error_codes/E0635.md create mode 100644 src/librustc_error_codes/error_codes/E0636.md create mode 100644 src/librustc_error_codes/error_codes/E0638.md create mode 100644 src/librustc_error_codes/error_codes/E0639.md create mode 100644 src/librustc_error_codes/error_codes/E0641.md create mode 100644 src/librustc_error_codes/error_codes/E0642.md create mode 100644 src/librustc_error_codes/error_codes/E0643.md create mode 100644 src/librustc_error_codes/error_codes/E0644.md create mode 100644 src/librustc_error_codes/error_codes/E0646.md create mode 100644 src/librustc_error_codes/error_codes/E0647.md create mode 100644 src/librustc_error_codes/error_codes/E0648.md create mode 100644 src/librustc_error_codes/error_codes/E0658.md create mode 100644 src/librustc_error_codes/error_codes/E0659.md create mode 100644 src/librustc_error_codes/error_codes/E0660.md create mode 100644 src/librustc_error_codes/error_codes/E0661.md create mode 100644 src/librustc_error_codes/error_codes/E0662.md create mode 100644 src/librustc_error_codes/error_codes/E0663.md create mode 100644 src/librustc_error_codes/error_codes/E0664.md create mode 100644 src/librustc_error_codes/error_codes/E0665.md create mode 100644 src/librustc_error_codes/error_codes/E0666.md create mode 100644 src/librustc_error_codes/error_codes/E0668.md create mode 100644 src/librustc_error_codes/error_codes/E0669.md create mode 100644 src/librustc_error_codes/error_codes/E0670.md create mode 100644 src/librustc_error_codes/error_codes/E0671.md create mode 100644 src/librustc_error_codes/error_codes/E0689.md create mode 100644 src/librustc_error_codes/error_codes/E0690.md create mode 100644 src/librustc_error_codes/error_codes/E0691.md create mode 100644 src/librustc_error_codes/error_codes/E0692.md create mode 100644 src/librustc_error_codes/error_codes/E0695.md create mode 100644 src/librustc_error_codes/error_codes/E0697.md create mode 100644 src/librustc_error_codes/error_codes/E0698.md create mode 100644 src/librustc_error_codes/error_codes/E0699.md create mode 100644 src/librustc_error_codes/error_codes/E0700.md create mode 100644 src/librustc_error_codes/error_codes/E0701.md create mode 100644 src/librustc_error_codes/error_codes/E0704.md create mode 100644 src/librustc_error_codes/error_codes/E0705.md create mode 100644 src/librustc_error_codes/error_codes/E0706.md create mode 100644 src/librustc_error_codes/error_codes/E0712.md create mode 100644 src/librustc_error_codes/error_codes/E0713.md create mode 100644 src/librustc_error_codes/error_codes/E0714.md create mode 100644 src/librustc_error_codes/error_codes/E0715.md create mode 100644 src/librustc_error_codes/error_codes/E0716.md create mode 100644 src/librustc_error_codes/error_codes/E0718.md create mode 100644 src/librustc_error_codes/error_codes/E0720.md create mode 100644 src/librustc_error_codes/error_codes/E0723.md create mode 100644 src/librustc_error_codes/error_codes/E0725.md create mode 100644 src/librustc_error_codes/error_codes/E0728.md create mode 100644 src/librustc_error_codes/error_codes/E0729.md create mode 100644 src/librustc_error_codes/error_codes/E0730.md create mode 100644 src/librustc_error_codes/error_codes/E0731.md create mode 100644 src/librustc_error_codes/error_codes/E0732.md create mode 100644 src/librustc_error_codes/error_codes/E0733.md create mode 100644 src/librustc_error_codes/error_codes/E0734.md create mode 100644 src/librustc_error_codes/error_codes/E0735.md create mode 100644 src/librustc_error_codes/error_codes/E0736.md create mode 100644 src/librustc_error_codes/error_codes/E0737.md create mode 100644 src/librustc_error_codes/error_codes/E0738.md create mode 100644 src/librustc_error_codes/error_codes/E0740.md create mode 100644 src/librustc_error_codes/error_codes/E0741.md create mode 100644 src/librustc_error_codes/error_codes/E0742.md create mode 100644 src/librustc_error_codes/error_codes/E0743.md create mode 100644 src/librustc_error_codes/error_codes/E0744.md create mode 100644 src/librustc_error_codes/error_codes/E0745.md create mode 100644 src/librustc_error_codes/lib.rs rename src/{libsyntax => librustc_errors}/json.rs (96%) rename src/{libsyntax => librustc_errors}/json/tests.rs (85%) create mode 100644 src/librustc_feature/Cargo.toml rename src/{libsyntax/feature_gate => librustc_feature}/accepted.rs (98%) rename src/{libsyntax/feature_gate => librustc_feature}/active.rs (92%) rename src/{libsyntax/feature_gate => librustc_feature}/builtin_attrs.rs (91%) create mode 100644 src/librustc_feature/lib.rs rename src/{libsyntax/feature_gate => librustc_feature}/removed.rs (92%) create mode 100644 src/librustc_lint/array_into_iter.rs delete mode 100644 src/librustc_lint/error_codes.rs create mode 100644 src/librustc_macros/src/lift.rs create mode 100644 src/librustc_macros/src/type_foldable.rs delete mode 100644 src/librustc_metadata/cstore.rs delete mode 100644 src/librustc_metadata/error_codes.rs rename src/librustc_metadata/{ => rmeta}/decoder.rs (76%) rename src/librustc_metadata/{ => rmeta/decoder}/cstore_impl.rs (92%) rename src/librustc_metadata/{ => rmeta}/encoder.rs (91%) rename src/librustc_metadata/{schema.rs => rmeta/mod.rs} (56%) rename src/librustc_metadata/{ => rmeta}/table.rs (69%) rename src/librustc_mir/borrow_check/{nll => }/constraint_generation.rs (95%) rename src/librustc_mir/borrow_check/{nll => }/constraints/graph.rs (97%) rename src/librustc_mir/borrow_check/{nll => }/constraints/mod.rs (98%) rename src/librustc_mir/borrow_check/{ => diagnostics}/conflict_errors.rs (86%) rename src/librustc_mir/borrow_check/{nll/explain_borrow/mod.rs => diagnostics/explain_borrow.rs} (97%) rename src/librustc_mir/borrow_check/{nll/explain_borrow => diagnostics}/find_use.rs (96%) rename src/librustc_mir/borrow_check/{error_reporting.rs => diagnostics/mod.rs} (91%) rename src/librustc_mir/borrow_check/{ => diagnostics}/move_errors.rs (91%) rename src/librustc_mir/borrow_check/{ => diagnostics}/mutability_errors.rs (86%) create mode 100644 src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs rename src/librustc_mir/borrow_check/{nll/region_infer/error_reporting/mod.rs => diagnostics/region_errors.rs} (93%) rename src/librustc_mir/borrow_check/{nll/region_infer/error_reporting => diagnostics}/region_name.rs (88%) rename src/librustc_mir/borrow_check/{nll/region_infer/error_reporting => diagnostics}/var_name.rs (90%) rename src/librustc_mir/borrow_check/{nll => }/facts.rs (91%) rename src/librustc_mir/borrow_check/{nll => }/invalidation.rs (96%) rename src/librustc_mir/borrow_check/{nll => }/member_constraints.rs (100%) rename src/librustc_mir/borrow_check/{nll/mod.rs => nll.rs} (80%) rename src/librustc_mir/borrow_check/{nll => }/region_infer/dump_mir.rs (100%) rename src/librustc_mir/borrow_check/{nll => }/region_infer/graphviz.rs (98%) rename src/librustc_mir/borrow_check/{nll => }/region_infer/mod.rs (86%) rename src/librustc_mir/borrow_check/{nll => }/region_infer/values.rs (99%) rename src/librustc_mir/borrow_check/{nll => }/renumber.rs (94%) rename src/librustc_mir/borrow_check/{nll => }/type_check/constraint_conversion.rs (95%) rename src/librustc_mir/borrow_check/{nll => }/type_check/free_region_relations.rs (97%) rename src/librustc_mir/borrow_check/{nll => }/type_check/input_output.rs (91%) rename src/librustc_mir/borrow_check/{nll => }/type_check/liveness/local_use_map.rs (97%) rename src/librustc_mir/borrow_check/{nll => }/type_check/liveness/mod.rs (91%) rename src/librustc_mir/borrow_check/{nll => }/type_check/liveness/polonius.rs (68%) rename src/librustc_mir/borrow_check/{nll => }/type_check/liveness/trace.rs (97%) rename src/librustc_mir/borrow_check/{nll => }/type_check/mod.rs (89%) rename src/librustc_mir/borrow_check/{nll => }/type_check/relate_tys.rs (96%) rename src/librustc_mir/borrow_check/{nll => }/universal_regions.rs (97%) delete mode 100644 src/librustc_mir/error_codes.rs delete mode 100644 src/librustc_mir/transform/qualify_consts.rs create mode 100644 src/librustc_mir/transform/simplify_try.rs delete mode 100644 src/librustc_mir/transform/uniform_array_move_out.rs create mode 100644 src/librustc_mir/transform/uninhabited_enum_branching.rs create mode 100644 src/librustc_parse/Cargo.toml rename src/{libsyntax => librustc_parse}/config.rs (71%) rename src/{libsyntax/parse => librustc_parse}/lexer/mod.rs (96%) rename src/{libsyntax/parse => librustc_parse}/lexer/tokentrees.rs (98%) rename src/{libsyntax/parse => librustc_parse/lexer}/unescape_error_reporting.rs (99%) rename src/{libsyntax/parse => librustc_parse}/lexer/unicode_chars.rs (99%) rename src/{libsyntax/parse/mod.rs => librustc_parse/lib.rs} (91%) rename src/{libsyntax/parse => librustc_parse}/parser/attr.rs (83%) rename src/{libsyntax/parse => librustc_parse}/parser/diagnostics.rs (95%) rename src/{libsyntax/parse => librustc_parse}/parser/expr.rs (95%) rename src/{libsyntax/parse => librustc_parse}/parser/generics.rs (97%) rename src/{libsyntax/parse => librustc_parse}/parser/item.rs (89%) rename src/{libsyntax/parse/parser.rs => librustc_parse/parser/mod.rs} (89%) rename src/{libsyntax/parse => librustc_parse}/parser/module.rs (84%) rename src/{libsyntax/parse => librustc_parse}/parser/pat.rs (96%) rename src/{libsyntax/parse => librustc_parse}/parser/path.rs (90%) rename src/{libsyntax/parse => librustc_parse}/parser/stmt.rs (95%) rename src/{libsyntax/parse => librustc_parse}/parser/ty.rs (96%) create mode 100644 src/librustc_parse/validate_attr.rs create mode 100644 src/librustc_passes/check_const.rs delete mode 100644 src/librustc_passes/error_codes.rs delete mode 100644 src/librustc_plugin/deprecated/Cargo.toml delete mode 100644 src/librustc_plugin/deprecated/lib.rs delete mode 100644 src/librustc_plugin/error_codes.rs delete mode 100644 src/librustc_plugin/lib.rs delete mode 100644 src/librustc_plugin/load.rs delete mode 100644 src/librustc_plugin/registry.rs rename src/{librustc_plugin => librustc_plugin_impl}/Cargo.toml (86%) rename src/{librustc_plugin => librustc_plugin_impl}/build.rs (100%) create mode 100644 src/librustc_plugin_impl/lib.rs create mode 100644 src/librustc_plugin_impl/load.rs delete mode 100644 src/librustc_privacy/error_codes.rs rename src/{librustc/hir/map => librustc_resolve}/def_collector.rs (93%) delete mode 100644 src/librustc_resolve/error_codes.rs create mode 100644 src/librustc_session/Cargo.toml rename src/{librustc/dep_graph => librustc_session}/cgu_reuse_tracker.rs (95%) rename src/{librustc/session => librustc_session}/code_stats.rs (90%) rename src/{librustc/session => librustc_session}/config.rs (88%) rename src/{librustc/session => librustc_session}/filesearch.rs (96%) create mode 100644 src/librustc_session/lib.rs create mode 100644 src/librustc_session/lint.rs create mode 100644 src/librustc_session/node_id.rs rename src/{libsyntax/sess.rs => librustc_session/parse.rs} (59%) rename src/{librustc/session => librustc_session}/search_paths.rs (90%) rename src/{librustc/session/mod.rs => librustc_session/session.rs} (91%) create mode 100644 src/librustc_session/utils.rs create mode 100644 src/librustc_target/spec/hermit_kernel_base.rs delete mode 100644 src/librustc_target/spec/i686_unknown_dragonfly.rs create mode 100644 src/librustc_target/spec/riscv64gc_unknown_linux_gnu.rs create mode 100644 src/librustc_target/spec/thumbv7neon_unknown_linux_musleabihf.rs create mode 100644 src/librustc_target/spec/x86_64_unknown_hermit_kernel.rs delete mode 100644 src/librustc_typeck/error_codes.rs rename src/{librustc/middle => librustc_typeck}/expr_use_visitor.rs (74%) create mode 100644 src/librustc_typeck/mem_categorization.rs create mode 100644 src/librustdoc/clean/types.rs create mode 100644 src/librustdoc/clean/utils.rs rename src/libstd/{collections/hash/bench.rs => benches/hash/map.rs} (88%) create mode 100644 src/libstd/benches/hash/mod.rs create mode 100644 src/libstd/benches/hash/set_ops.rs create mode 100644 src/libstd/benches/lib.rs delete mode 100644 src/libsyntax/error_codes.rs delete mode 100644 src/libsyntax/feature_gate/mod.rs rename src/libsyntax/{parse => }/token.rs (93%) rename src/libsyntax/{parse => util}/classify.rs (100%) rename src/libsyntax/{parse/lexer => util}/comments.rs (91%) rename src/libsyntax/{parse/lexer => util}/comments/tests.rs (100%) rename src/libsyntax/{parse => util}/literal.rs (91%) rename src/{libsyntax => libsyntax_expand}/mut_visit/tests.rs (94%) rename src/{libsyntax => libsyntax_expand}/parse/lexer/tests.rs (95%) rename src/{libsyntax => libsyntax_expand}/parse/tests.rs (90%) rename src/{libsyntax => libsyntax_expand}/tests.rs (98%) rename src/{libsyntax => libsyntax_expand}/tokenstream/tests.rs (94%) delete mode 100644 src/libsyntax_ext/error_codes.rs delete mode 100644 src/libsyntax_ext/plugin_macro_defs.rs rename src/{librustc/ich => libsyntax_pos}/caching_source_map_view.rs (97%) create mode 100644 src/libsyntax_pos/fatal_error.rs rename src/{libsyntax => libsyntax_pos}/source_map.rs (95%) rename src/{libsyntax => libsyntax_pos}/source_map/tests.rs (100%) create mode 100644 src/test/codegen/bool-cmp.rs create mode 100644 src/test/codegen/sanitizer-memory-track-orgins.rs create mode 100644 src/test/codegen/sanitizer-recover.rs create mode 100644 src/test/codegen/set-discriminant-invalid.rs create mode 100644 src/test/codegen/try_identity.rs create mode 100644 src/test/debuginfo/pretty-std-collections-hash.rs create mode 100644 src/test/incremental/delayed_span_bug.rs create mode 100644 src/test/incremental/issue-61323.rs create mode 100644 src/test/mir-opt/const-promotion-extern-static.rs create mode 100644 src/test/mir-opt/const_prop/issue-66971.rs create mode 100644 src/test/mir-opt/const_prop/issue-67019.rs create mode 100644 src/test/mir-opt/const_prop/return_place.rs create mode 100644 src/test/mir-opt/inline-closure-captures.rs create mode 100644 src/test/mir-opt/retain-never-const.rs create mode 100644 src/test/mir-opt/simplify-arm-identity.rs create mode 100644 src/test/mir-opt/simplify_try.rs create mode 100644 src/test/mir-opt/uninhabited_enum_branching.rs create mode 100644 src/test/pretty/enum-variant-vis.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-fun/rustc.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/Makefile create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/foo.rs create mode 100644 src/test/run-make-fulldeps/glibc-staticlib-args/Makefile create mode 100644 src/test/run-make-fulldeps/glibc-staticlib-args/library.rs create mode 100644 src/test/run-make-fulldeps/glibc-staticlib-args/program.c create mode 100644 src/test/run-make-fulldeps/pgo-branch-weights/Makefile create mode 100644 src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt create mode 100644 src/test/run-make-fulldeps/pgo-branch-weights/interesting.rs create mode 100644 src/test/run-make-fulldeps/pgo-branch-weights/main.rs create mode 100644 src/test/run-make-fulldeps/pgo-branch-weights/opaque.rs create mode 100644 src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile create mode 100644 src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt create mode 100644 src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs create mode 100644 src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs create mode 100644 src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs delete mode 100644 src/test/run-make-fulldeps/pretty-print-path-suffix/Makefile delete mode 100644 src/test/run-make-fulldeps/pretty-print-path-suffix/foo.pp delete mode 100644 src/test/run-make-fulldeps/pretty-print-path-suffix/foo_method.pp delete mode 100644 src/test/run-make-fulldeps/pretty-print-path-suffix/input.rs delete mode 100644 src/test/run-make-fulldeps/pretty-print-path-suffix/nest_foo.pp create mode 100644 src/test/run-make-fulldeps/rustdoc-themes/Makefile create mode 100644 src/test/run-make-fulldeps/rustdoc-themes/foo.rs create mode 100644 src/test/rustdoc-ui/intra-links-anchors.rs create mode 100644 src/test/rustdoc-ui/intra-links-anchors.stderr create mode 100644 src/test/rustdoc-ui/issue-61732.rs create mode 100644 src/test/rustdoc-ui/issue-61732.stderr create mode 100644 src/test/rustdoc/auxiliary/issue-66159-1.rs create mode 100644 src/test/rustdoc/duplicate-cfg.rs create mode 100644 src/test/rustdoc/intra-doc-link-enum-struct-field.rs create mode 100644 src/test/rustdoc/intra-links-anchors.rs delete mode 100644 src/test/rustdoc/issue-46380.rs create mode 100644 src/test/rustdoc/issue-66159.rs create mode 100644 src/test/rustdoc/issue-67851-both.rs create mode 100644 src/test/rustdoc/issue-67851-hidden.rs create mode 100644 src/test/rustdoc/issue-67851-neither.rs create mode 100644 src/test/rustdoc/issue-67851-private.rs delete mode 100644 src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs create mode 100644 src/test/ui-fulldeps/auxiliary/empty-plugin.rs delete mode 100644 src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs delete mode 100644 src/test/ui-fulldeps/auxiliary/plugin-args.rs delete mode 100644 src/test/ui-fulldeps/auxiliary/roman-numerals.rs rename src/test/{ui/feature-gates => ui-fulldeps}/feature-gate-plugin.rs (60%) rename src/test/{ui/feature-gates => ui-fulldeps}/feature-gate-plugin.stderr (67%) delete mode 100644 src/test/ui-fulldeps/llvm-pass-plugin.rs delete mode 100644 src/test/ui-fulldeps/llvm-pass-plugin.stderr create mode 100644 src/test/ui-fulldeps/pathless-extern-unstable.rs create mode 100644 src/test/ui-fulldeps/pathless-extern-unstable.stderr delete mode 100644 src/test/ui-fulldeps/plugin-args-1.rs delete mode 100644 src/test/ui-fulldeps/plugin-args-1.stderr delete mode 100644 src/test/ui-fulldeps/plugin-args-2.rs delete mode 100644 src/test/ui-fulldeps/plugin-args-2.stderr delete mode 100644 src/test/ui-fulldeps/plugin-args-3.rs delete mode 100644 src/test/ui-fulldeps/plugin-args-3.stderr create mode 100644 src/test/ui-fulldeps/plugin-args.rs create mode 100644 src/test/ui-fulldeps/plugin-args.stderr delete mode 100644 src/test/ui-fulldeps/plugin-as-extern-crate.stderr delete mode 100644 src/test/ui-fulldeps/plugin-attr-register-deny.rs delete mode 100644 src/test/ui-fulldeps/plugin-attr-register-deny.stderr delete mode 100644 src/test/ui-fulldeps/plugin-reexport.rs delete mode 100644 src/test/ui-fulldeps/plugin-reexport.stderr delete mode 100644 src/test/ui-fulldeps/roman-numerals-macro.rs delete mode 100644 src/test/ui-fulldeps/roman-numerals-macro.stderr create mode 100644 src/test/ui/asm/asm-literal-escaping.rs create mode 100644 src/test/ui/async-await/async-trait-fn.rs create mode 100644 src/test/ui/async-await/async-trait-fn.stderr create mode 100644 src/test/ui/async-await/issue-64130-1-sync.rs create mode 100644 src/test/ui/async-await/issue-64130-1-sync.stderr create mode 100644 src/test/ui/async-await/issue-64130-2-send.rs create mode 100644 src/test/ui/async-await/issue-64130-2-send.stderr create mode 100644 src/test/ui/async-await/issue-64130-3-other.rs create mode 100644 src/test/ui/async-await/issue-64130-3-other.stderr create mode 100644 src/test/ui/async-await/issue-64130-4-async-move.rs create mode 100644 src/test/ui/async-await/issue-64130-4-async-move.stderr create mode 100644 src/test/ui/async-await/issue-67252-unnamed-future.rs create mode 100644 src/test/ui/async-await/issue-67252-unnamed-future.stderr create mode 100644 src/test/ui/async-await/issues/issue-62097.nll.stderr create mode 100644 src/test/ui/async-await/issues/issue-62097.rs create mode 100644 src/test/ui/async-await/issues/issue-62097.stderr create mode 100644 src/test/ui/async-await/issues/issue-64477-2.rs create mode 100644 src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs create mode 100644 src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs create mode 100644 src/test/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs create mode 100644 src/test/ui/async-await/issues/issue-66695-static-refs.rs create mode 100644 src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs create mode 100644 src/test/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr create mode 100644 src/test/ui/async-await/issues/issue-67611-static-mut-refs.rs create mode 100644 src/test/ui/attributes/register-attr-tool-fail.rs create mode 100644 src/test/ui/attributes/register-attr-tool-fail.stderr create mode 100644 src/test/ui/attributes/register-attr-tool-import.rs create mode 100644 src/test/ui/attributes/register-attr-tool-import.stderr create mode 100644 src/test/ui/attributes/register-attr-tool-prelude.rs create mode 100644 src/test/ui/attributes/register-attr-tool-prelude.stderr create mode 100644 src/test/ui/attributes/register-attr-tool-unused.rs create mode 100644 src/test/ui/attributes/register-attr-tool-unused.stderr create mode 100644 src/test/ui/attributes/register-attr-tool.rs create mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs create mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs create mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array-use.rs create mode 100644 src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr create mode 100644 src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs create mode 100644 src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs create mode 100644 src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr create mode 100644 src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs rename src/test/ui/borrowck/{borrowck-slice-pattern-element-loan.rs => borrowck-slice-pattern-element-loan-slice.rs} (65%) rename src/test/ui/borrowck/{borrowck-slice-pattern-element-loan.stderr => borrowck-slice-pattern-element-loan-slice.stderr} (89%) create mode 100644 src/test/ui/borrowck/move-from-union-field-issue-66500.rs create mode 100644 src/test/ui/borrowck/move-from-union-field-issue-66500.stderr create mode 100644 src/test/ui/borrowck/slice-index-bounds-check-invalidation.rs create mode 100644 src/test/ui/borrowck/slice-index-bounds-check-invalidation.stderr create mode 100644 src/test/ui/cfg-rustdoc.rs create mode 100644 src/test/ui/cfg-rustdoc.stderr create mode 100644 src/test/ui/closures/closure-expected-type/expect-region-supply-region.polonius.stderr create mode 100644 src/test/ui/closures/issue-67123.rs create mode 100644 src/test/ui/closures/issue-67123.stderr delete mode 100644 src/test/ui/coherence/coherence-all-remote.re.stderr rename src/test/ui/coherence/{coherence-all-remote.old.stderr => coherence-all-remote.stderr} (73%) delete mode 100644 src/test/ui/coherence/coherence-bigint-param.old.stderr delete mode 100644 src/test/ui/coherence/coherence-bigint-param.re.stderr create mode 100644 src/test/ui/coherence/coherence-bigint-param.stderr delete mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.re.stderr rename src/test/ui/coherence/{coherence-blanket-conflicts-with-blanket-implemented.old.stderr => coherence-blanket-conflicts-with-blanket-implemented.stderr} (98%) delete mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.old.stderr rename src/test/ui/coherence/{coherence-blanket-conflicts-with-blanket-unimplemented.re.stderr => coherence-blanket-conflicts-with-blanket-unimplemented.stderr} (97%) delete mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.re.stderr rename src/test/ui/coherence/{coherence-blanket-conflicts-with-specific-cross-crate.old.stderr => coherence-blanket-conflicts-with-specific-cross-crate.stderr} (98%) delete mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.re.stderr rename src/test/ui/coherence/{coherence-blanket-conflicts-with-specific-multidispatch.old.stderr => coherence-blanket-conflicts-with-specific-multidispatch.stderr} (97%) delete mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific-trait.re.stderr rename src/test/ui/coherence/{coherence-blanket-conflicts-with-specific-trait.old.stderr => coherence-blanket-conflicts-with-specific-trait.stderr} (86%) delete mode 100644 src/test/ui/coherence/coherence-blanket-conflicts-with-specific.re.stderr rename src/test/ui/coherence/{coherence-blanket-conflicts-with-specific.old.stderr => coherence-blanket-conflicts-with-specific.stderr} (86%) delete mode 100644 src/test/ui/coherence/coherence-conflicting-negative-trait-impl.re.stderr rename src/test/ui/coherence/{coherence-conflicting-negative-trait-impl.old.stderr => coherence-conflicting-negative-trait-impl.stderr} (87%) delete mode 100644 src/test/ui/coherence/coherence-cow.a.stderr delete mode 100644 src/test/ui/coherence/coherence-cow.b.stderr delete mode 100644 src/test/ui/coherence/coherence-cow.c.stderr delete mode 100644 src/test/ui/coherence/coherence-cross-crate-conflict.re.stderr rename src/test/ui/coherence/{coherence-cross-crate-conflict.old.stderr => coherence-cross-crate-conflict.stderr} (77%) delete mode 100644 src/test/ui/coherence/coherence-default-trait-impl.re.stderr rename src/test/ui/coherence/{coherence-default-trait-impl.old.stderr => coherence-default-trait-impl.stderr} (82%) delete mode 100644 src/test/ui/coherence/coherence-error-suppression.old.stderr rename src/test/ui/coherence/{coherence-error-suppression.re.stderr => coherence-error-suppression.stderr} (84%) delete mode 100644 src/test/ui/coherence/coherence-fundamental-trait-objects.re.stderr rename src/test/ui/coherence/{coherence-fundamental-trait-objects.old.stderr => coherence-fundamental-trait-objects.stderr} (90%) delete mode 100644 src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr rename src/test/ui/coherence/{coherence-impl-trait-for-trait-object-safe.old.stderr => coherence-impl-trait-for-trait-object-safe.stderr} (88%) delete mode 100644 src/test/ui/coherence/coherence-impl-trait-for-trait.re.stderr rename src/test/ui/coherence/{coherence-impl-trait-for-trait.old.stderr => coherence-impl-trait-for-trait.stderr} (88%) delete mode 100644 src/test/ui/coherence/coherence-impls-copy.re.stderr rename src/test/ui/coherence/{coherence-impls-copy.old.stderr => coherence-impls-copy.stderr} (88%) delete mode 100644 src/test/ui/coherence/coherence-impls-send.old.stderr rename src/test/ui/coherence/{coherence-impls-send.re.stderr => coherence-impls-send.stderr} (93%) delete mode 100644 src/test/ui/coherence/coherence-impls-sized.re.stderr rename src/test/ui/coherence/{coherence-impls-sized.old.stderr => coherence-impls-sized.stderr} (91%) delete mode 100644 src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.re.stderr rename src/test/ui/coherence/{coherence-inherited-assoc-ty-cycle-err.old.stderr => coherence-inherited-assoc-ty-cycle-err.stderr} (78%) delete mode 100644 src/test/ui/coherence/coherence-lone-type-parameter.re.stderr rename src/test/ui/coherence/{coherence-lone-type-parameter.old.stderr => coherence-lone-type-parameter.stderr} (71%) delete mode 100644 src/test/ui/coherence/coherence-negative-impls-safe.re.stderr rename src/test/ui/coherence/{coherence-negative-impls-safe.old.stderr => coherence-negative-impls-safe.stderr} (82%) delete mode 100644 src/test/ui/coherence/coherence-no-direct-lifetime-dispatch.re.stderr rename src/test/ui/coherence/{coherence-no-direct-lifetime-dispatch.old.stderr => coherence-no-direct-lifetime-dispatch.stderr} (86%) delete mode 100644 src/test/ui/coherence/coherence-orphan.re.stderr rename src/test/ui/coherence/{coherence-orphan.old.stderr => coherence-orphan.stderr} (93%) delete mode 100644 src/test/ui/coherence/coherence-overlap-all-t-and-tuple.re.stderr rename src/test/ui/coherence/{coherence-overlap-all-t-and-tuple.old.stderr => coherence-overlap-all-t-and-tuple.stderr} (88%) delete mode 100644 src/test/ui/coherence/coherence-overlap-downstream-inherent.re.stderr rename src/test/ui/coherence/{coherence-overlap-downstream-inherent.old.stderr => coherence-overlap-downstream-inherent.stderr} (86%) delete mode 100644 src/test/ui/coherence/coherence-overlap-downstream.re.stderr rename src/test/ui/coherence/{coherence-overlap-downstream.old.stderr => coherence-overlap-downstream.stderr} (88%) delete mode 100644 src/test/ui/coherence/coherence-overlap-issue-23516-inherent.re.stderr rename src/test/ui/coherence/{coherence-overlap-issue-23516-inherent.old.stderr => coherence-overlap-issue-23516-inherent.stderr} (89%) delete mode 100644 src/test/ui/coherence/coherence-overlap-issue-23516.re.stderr rename src/test/ui/coherence/{coherence-overlap-issue-23516.old.stderr => coherence-overlap-issue-23516.stderr} (91%) delete mode 100644 src/test/ui/coherence/coherence-overlap-messages.re.stderr rename src/test/ui/coherence/{coherence-overlap-messages.old.stderr => coherence-overlap-messages.stderr} (88%) delete mode 100644 src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr rename src/test/ui/coherence/{coherence-overlap-upstream-inherent.old.stderr => coherence-overlap-upstream-inherent.stderr} (89%) delete mode 100644 src/test/ui/coherence/coherence-overlap-upstream.re.stderr rename src/test/ui/coherence/{coherence-overlap-upstream.old.stderr => coherence-overlap-upstream.stderr} (91%) delete mode 100644 src/test/ui/coherence/coherence-overlapping-pairs.old.stderr rename src/test/ui/coherence/{coherence-overlapping-pairs.re.stderr => coherence-overlapping-pairs.stderr} (91%) delete mode 100644 src/test/ui/coherence/coherence-pair-covered-uncovered-1.old.stderr rename src/test/ui/coherence/{coherence-pair-covered-uncovered-1.re.stderr => coherence-pair-covered-uncovered-1.stderr} (92%) delete mode 100644 src/test/ui/coherence/coherence-pair-covered-uncovered.old.stderr rename src/test/ui/coherence/{coherence-pair-covered-uncovered.re.stderr => coherence-pair-covered-uncovered.stderr} (91%) delete mode 100644 src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr rename src/test/ui/coherence/{coherence-projection-conflict-orphan.old.stderr => coherence-projection-conflict-orphan.stderr} (90%) delete mode 100644 src/test/ui/coherence/coherence-projection-conflict-ty-param.re.stderr rename src/test/ui/coherence/{coherence-projection-conflict-ty-param.old.stderr => coherence-projection-conflict-ty-param.stderr} (88%) delete mode 100644 src/test/ui/coherence/coherence-projection-conflict.re.stderr rename src/test/ui/coherence/{coherence-projection-conflict.old.stderr => coherence-projection-conflict.stderr} (89%) delete mode 100644 src/test/ui/coherence/coherence-tuple-conflict.re.stderr rename src/test/ui/coherence/{coherence-tuple-conflict.old.stderr => coherence-tuple-conflict.stderr} (89%) delete mode 100644 src/test/ui/coherence/coherence-vec-local-2.old.stderr rename src/test/ui/coherence/{coherence-vec-local-2.re.stderr => coherence-vec-local-2.stderr} (92%) delete mode 100644 src/test/ui/coherence/coherence-vec-local.old.stderr rename src/test/ui/coherence/{coherence-vec-local.re.stderr => coherence-vec-local.stderr} (92%) delete mode 100644 src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr rename src/test/ui/coherence/{coherence_copy_like_err_fundamental_struct_tuple.old.stderr => coherence_copy_like_err_fundamental_struct_tuple.stderr} (99%) delete mode 100644 src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr rename src/test/ui/coherence/{coherence_copy_like_err_struct.old.stderr => coherence_copy_like_err_struct.stderr} (92%) delete mode 100644 src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr rename src/test/ui/coherence/{coherence_copy_like_err_tuple.old.stderr => coherence_copy_like_err_tuple.stderr} (91%) delete mode 100644 src/test/ui/coherence/coherence_inherent.re.stderr rename src/test/ui/coherence/{coherence_inherent.old.stderr => coherence_inherent.stderr} (92%) delete mode 100644 src/test/ui/coherence/coherence_inherent_cc.re.stderr rename src/test/ui/coherence/{coherence_inherent_cc.old.stderr => coherence_inherent_cc.stderr} (92%) delete mode 100644 src/test/ui/coherence/coherence_local_err_struct.re.stderr rename src/test/ui/coherence/{coherence_local_err_struct.old.stderr => coherence_local_err_struct.stderr} (92%) delete mode 100644 src/test/ui/coherence/coherence_local_err_tuple.old.stderr rename src/test/ui/coherence/{coherence_local_err_tuple.re.stderr => coherence_local_err_tuple.stderr} (92%) create mode 100644 src/test/ui/command/command-argv0-debug.rs create mode 100644 src/test/ui/command/command-argv0.rs rename src/test/ui/{ => command}/command-exec.rs (100%) rename src/test/ui/{ => command}/command-pre-exec.rs (100%) rename src/test/ui/{ => command}/command-uid-gid.rs (100%) create mode 100644 src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.rs create mode 100644 src/test/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr delete mode 100644 src/test/ui/consts/const-eval/const_caller_location.rs create mode 100644 src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs create mode 100644 src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr create mode 100644 src/test/ui/consts/const-eval/issue-62272.stderr delete mode 100644 src/test/ui/consts/const-eval/issue-64970.stderr create mode 100644 src/test/ui/consts/const-eval/panic-assoc-never-type.rs create mode 100644 src/test/ui/consts/const-eval/panic-assoc-never-type.stderr create mode 100644 src/test/ui/consts/const-eval/panic-never-type.rs create mode 100644 src/test/ui/consts/const-eval/panic-never-type.stderr create mode 100644 src/test/ui/consts/const-eval/promote-static.rs create mode 100644 src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs create mode 100644 src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr create mode 100644 src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs create mode 100644 src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr create mode 100644 src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs create mode 100644 src/test/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr create mode 100644 src/test/ui/consts/const-fn-zst-args.rs delete mode 100644 src/test/ui/consts/const-if.rs delete mode 100644 src/test/ui/consts/const-if.stderr create mode 100644 src/test/ui/consts/const-labeled-break.stderr create mode 100644 src/test/ui/consts/const-mut-refs/const_mut_refs.rs create mode 100644 src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs create mode 100644 src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr create mode 100644 src/test/ui/consts/const_let_promote.rs create mode 100644 src/test/ui/consts/control-flow/assert.both.stderr create mode 100644 src/test/ui/consts/control-flow/assert.if_match.stderr create mode 100644 src/test/ui/consts/control-flow/assert.panic.stderr create mode 100644 src/test/ui/consts/control-flow/assert.rs create mode 100644 src/test/ui/consts/control-flow/assert.stock.stderr create mode 100644 src/test/ui/consts/control-flow/basics.rs create mode 100644 src/test/ui/consts/control-flow/drop-failure.rs create mode 100644 src/test/ui/consts/control-flow/drop-failure.stderr create mode 100644 src/test/ui/consts/control-flow/drop-success.rs create mode 100644 src/test/ui/consts/control-flow/exhaustive-c-like-enum-match.rs create mode 100644 src/test/ui/consts/control-flow/feature-gate-const-if-match.if_match.stderr create mode 100644 src/test/ui/consts/control-flow/feature-gate-const-if-match.rs create mode 100644 src/test/ui/consts/control-flow/feature-gate-const-if-match.stock.stderr create mode 100644 src/test/ui/consts/control-flow/interior-mutability.rs create mode 100644 src/test/ui/consts/control-flow/interior-mutability.stderr create mode 100644 src/test/ui/consts/control-flow/issue-46843.if_match.stderr create mode 100644 src/test/ui/consts/control-flow/issue-46843.rs create mode 100644 src/test/ui/consts/control-flow/issue-46843.stock.stderr rename src/test/ui/{issues/issue-50577.stderr => consts/control-flow/issue-50577.if_match.stderr} (80%) create mode 100644 src/test/ui/consts/control-flow/issue-50577.rs create mode 100644 src/test/ui/consts/control-flow/issue-50577.stock.stderr create mode 100644 src/test/ui/consts/control-flow/loop.both.stderr create mode 100644 src/test/ui/consts/control-flow/loop.if_match.stderr create mode 100644 src/test/ui/consts/control-flow/loop.loop_.stderr create mode 100644 src/test/ui/consts/control-flow/loop.rs create mode 100644 src/test/ui/consts/control-flow/loop.stock.stderr create mode 100644 src/test/ui/consts/control-flow/short-circuit-let.rs create mode 100644 src/test/ui/consts/control-flow/short-circuit.if_match.stderr create mode 100644 src/test/ui/consts/control-flow/short-circuit.rs create mode 100644 src/test/ui/consts/control-flow/short-circuit.stock.stderr create mode 100644 src/test/ui/consts/control-flow/single_variant_match_ice.rs create mode 100644 src/test/ui/consts/control-flow/try.rs create mode 100644 src/test/ui/consts/control-flow/try.stderr create mode 100644 src/test/ui/consts/huge-values.rs create mode 100644 src/test/ui/consts/issue-52432.rs create mode 100644 src/test/ui/consts/issue-52432.stderr create mode 100644 src/test/ui/consts/issue-66345.rs create mode 100644 src/test/ui/consts/issue-66787.rs delete mode 100644 src/test/ui/consts/miri_unleashed/enum_discriminants.stderr create mode 100644 src/test/ui/consts/miri_unleashed/read_from_static.rs create mode 100644 src/test/ui/consts/projection_qualif.mut_refs.stderr rename src/test/ui/consts/{projection_qualif.stderr => projection_qualif.stock.stderr} (56%) create mode 100644 src/test/ui/consts/promote_borrowed_field.rs delete mode 100644 src/test/ui/consts/rfc-2203-const-array-repeat-exprs/const-fns.rs create mode 100644 src/test/ui/consts/rfc-2203-const-array-repeat-exprs/fn-call-in-const.rs create mode 100644 src/test/ui/consts/rfc-2203-const-array-repeat-exprs/fn-call-in-non-const.rs rename src/test/ui/consts/rfc-2203-const-array-repeat-exprs/{const-fns.stderr => fn-call-in-non-const.stderr} (63%) delete mode 100644 src/test/ui/consts/single_variant_match_ice.rs delete mode 100644 src/test/ui/consts/single_variant_match_ice.stderr create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr rename src/test/ui/consts/{static_mut_containing_mut_ref2.stderr => static_mut_containing_mut_ref2.stock.stderr} (51%) create mode 100644 src/test/ui/consts/unstable-const-fn-in-libcore.rs create mode 100644 src/test/ui/consts/unstable-const-fn-in-libcore.stderr rename src/test/ui/{consts/miri_unleashed/enum_discriminants.rs => enum-discriminant/niche.rs} (98%) create mode 100644 src/test/ui/enum/nested-enum.rs create mode 100644 src/test/ui/enum/nested-enum.stderr create mode 100644 src/test/ui/enum/union-in-enum.rs create mode 100644 src/test/ui/extern-flag/auxiliary/somedep.rs create mode 100644 src/test/ui/extern-flag/multiple-opts.rs create mode 100644 src/test/ui/extern-flag/multiple-opts.stderr create mode 100644 src/test/ui/extern-flag/noprelude-and-prelude.rs create mode 100644 src/test/ui/extern-flag/noprelude-resolves.rs create mode 100644 src/test/ui/extern-flag/noprelude.rs create mode 100644 src/test/ui/extern-flag/noprelude.stderr create mode 100644 src/test/ui/extern-flag/public-and-private.rs create mode 100644 src/test/ui/extern-flag/public-and-private.stderr delete mode 100644 src/test/ui/extern/extern-prelude-core.stderr delete mode 100644 src/test/ui/extern/extern-prelude-std.stderr create mode 100644 src/test/ui/extern/issue-36122-accessing-externed-dst.rs create mode 100644 src/test/ui/extern/issue-36122-accessing-externed-dst.stderr create mode 100644 src/test/ui/feature-gate/unstable-attribute-allow-issue-none.rs create mode 100644 src/test/ui/feature-gate/unstable-attribute-allow-issue-none.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-cfg_sanitize.rs create mode 100644 src/test/ui/feature-gates/feature-gate-cfg_sanitize.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-on-unimplemented.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-re-rebalance-coherence.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-register_attr.rs create mode 100644 src/test/ui/feature-gates/feature-gate-register_attr.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-register_tool.rs create mode 100644 src/test/ui/feature-gates/feature-gate-register_tool.stderr create mode 100644 src/test/ui/generator/async-generator-issue-67158.rs create mode 100644 src/test/ui/generator/async-generator-issue-67158.stderr create mode 100644 src/test/ui/generator/static-mut-reference-across-yield.rs create mode 100644 src/test/ui/generator/static-reference-across-yield.rs create mode 100644 src/test/ui/hrtb/hrtb-perfect-forwarding.polonius.stderr delete mode 100644 src/test/ui/hygiene/dollar-crate-modern.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr create mode 100644 src/test/ui/impl-trait/type-alias-generic-param.rs create mode 100644 src/test/ui/impl-trait/where-allowed-2.rs create mode 100644 src/test/ui/impl-trait/where-allowed-2.stderr delete mode 100644 src/test/ui/issues/auxiliary/issue-38715-modern.rs delete mode 100644 src/test/ui/issues/auxiliary/issue-38715.rs delete mode 100644 src/test/ui/issues/issue-15108.rs create mode 100644 src/test/ui/issues/issue-34721.fixed delete mode 100644 src/test/ui/issues/issue-38715-rpass.rs create mode 100644 src/test/ui/issues/issue-40231-1.rs create mode 100644 src/test/ui/issues/issue-40231-2.rs delete mode 100644 src/test/ui/issues/issue-46843.rs delete mode 100644 src/test/ui/issues/issue-46843.stderr delete mode 100644 src/test/ui/issues/issue-50577.rs delete mode 100644 src/test/ui/issues/issue-52057.stderr delete mode 100644 src/test/ui/issues/issue-57399-self-return-impl-trait.stderr create mode 100644 src/test/ui/issues/issue-62480.rs create mode 100644 src/test/ui/issues/issue-62480.stderr create mode 100644 src/test/ui/issues/issue-65634-raw-ident-suggestion.rs create mode 100644 src/test/ui/issues/issue-65634-raw-ident-suggestion.stderr create mode 100644 src/test/ui/issues/issue-66702-break-outside-loop-val.rs create mode 100644 src/test/ui/issues/issue-66702-break-outside-loop-val.stderr create mode 100644 src/test/ui/issues/issue-66851.rs create mode 100644 src/test/ui/issues/issue-67039-unsound-pin-partialeq.rs create mode 100644 src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr create mode 100644 src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs create mode 100644 src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr create mode 100644 src/test/ui/issues/issue-68091-unicode-ident-after-if.rs create mode 100644 src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr create mode 100644 src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs create mode 100644 src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr create mode 100644 src/test/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs create mode 100644 src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs create mode 100644 src/test/ui/iterators/into-iter-on-arrays-lint.fixed create mode 100644 src/test/ui/iterators/into-iter-on-arrays-lint.rs create mode 100644 src/test/ui/iterators/into-iter-on-arrays-lint.stderr create mode 100644 src/test/ui/label/label-beginning-with-underscore.rs create mode 100644 src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs create mode 100644 src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr rename src/test/ui/{dead-code-alias-in-pat.rs => lint/dead-code/alias-in-pat.rs} (100%) rename src/test/ui/{lint-dead-code-associated-type.rs => lint/dead-code/associated-type.rs} (100%) rename src/test/ui/{fail-no-dead-code.rs => lint/dead-code/basic.rs} (100%) rename src/test/ui/{fail-no-dead-code.stderr => lint/dead-code/basic.stderr} (68%) rename src/test/ui/{dead-code-closure-bang.rs => lint/dead-code/closure-bang.rs} (100%) rename src/test/ui/lint/{lint-dead-code-const-and-self.rs => dead-code/const-and-self.rs} (100%) rename src/test/ui/lint/{lint-dead-code-empty-unused-enum.rs => dead-code/empty-unused-enum.rs} (100%) rename src/test/ui/lint/{lint-dead-code-empty-unused-enum.stderr => dead-code/empty-unused-enum.stderr} (67%) rename src/test/ui/lint/{lint-dead-code-empty-unused-enum-pub.rs => dead-code/empty-unused-public-enum.rs} (100%) rename src/test/ui/{lint-dead-code-variant.rs => lint/dead-code/enum-variants.rs} (100%) rename src/test/ui/lint/{lint-dead-code-impl-trait.rs => dead-code/impl-trait.rs} (100%) rename src/test/ui/lint/{lint-dead-code-impl-trait.stderr => dead-code/impl-trait.stderr} (71%) rename src/test/ui/{dead-code-leading-underscore.rs => lint/dead-code/leading-underscore.rs} (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-1.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-1.stderr (73%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-2.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-2.stderr (69%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-3.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-3.stderr (80%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-4.rs (85%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-4.stderr (84%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-5.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-5.stderr (92%) create mode 100644 src/test/ui/lint/dead-code/newline-span.rs create mode 100644 src/test/ui/lint/dead-code/newline-span.stderr rename src/test/ui/{dead-code-tuple-struct-field.rs => lint/dead-code/tuple-struct-field.rs} (100%) rename src/test/ui/lint/{lint-dead-code-type-alias.rs => dead-code/type-alias.rs} (100%) rename src/test/ui/lint/{lint-dead-code-type-alias.stderr => dead-code/type-alias.stderr} (71%) rename src/test/ui/lint/{lint-dead-code-unused-enum.rs => dead-code/unused-enum.rs} (100%) rename src/test/ui/lint/{lint-dead-code-unused-enum.stderr => dead-code/unused-enum.stderr} (61%) rename src/test/ui/lint/{lint-dead-code-unused-variant.rs => dead-code/unused-struct-variant.rs} (100%) rename src/test/ui/lint/{lint-dead-code-unused-variant.stderr => dead-code/unused-struct-variant.stderr} (73%) rename src/test/ui/lint/{lint-dead-code-unused-variant-pub.rs => dead-code/unused-variant-pub.rs} (100%) rename src/test/ui/lint/{lint-dead-code-variant.rs => dead-code/unused-variant.rs} (100%) rename src/test/ui/lint/{lint-dead-code-variant.stderr => dead-code/unused-variant.stderr} (72%) rename src/test/ui/{fail-no-dead-code-core.rs => lint/dead-code/with-core-crate.rs} (100%) rename src/test/ui/{fail-no-dead-code-core.stderr => lint/dead-code/with-core-crate.stderr} (65%) rename src/test/ui/{dead-code-impl.rs => lint/dead-code/with-impl.rs} (100%) delete mode 100644 src/test/ui/macros/macro-path-prelude-pass.stderr create mode 100644 src/test/ui/malformed/malformed-meta-delim.rs create mode 100644 src/test/ui/malformed/malformed-meta-delim.stderr create mode 100644 src/test/ui/mir/issue66339.rs create mode 100644 src/test/ui/mir/mir_assign_eval_order.rs create mode 100644 src/test/ui/never_type/auto-traits.rs create mode 100644 src/test/ui/never_type/feature-gate-never_type_fallback.rs create mode 100644 src/test/ui/never_type/feature-gate-never_type_fallback.stderr create mode 100644 src/test/ui/never_type/never-value-fallback-issue-66757.rs create mode 100644 src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs create mode 100644 src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr create mode 100644 src/test/ui/nll/issue-69114-static-mut-ty.rs create mode 100644 src/test/ui/nll/issue-69114-static-mut-ty.stderr create mode 100644 src/test/ui/nll/issue-69114-static-ty.rs create mode 100644 src/test/ui/nll/issue-69114-static-ty.stderr create mode 100644 src/test/ui/nll/outlives-suggestion-more.rs create mode 100644 src/test/ui/nll/outlives-suggestion-more.stderr create mode 100644 src/test/ui/nll/outlives-suggestion-simple.polonius.stderr create mode 100644 src/test/ui/nll/outlives-suggestion-simple.rs create mode 100644 src/test/ui/nll/outlives-suggestion-simple.stderr create mode 100644 src/test/ui/nll/polonius/subset-relations.rs create mode 100644 src/test/ui/nll/polonius/subset-relations.stderr create mode 100644 src/test/ui/nll/user-annotations/closure-substs.polonius.stderr create mode 100644 src/test/ui/on-unimplemented/enclosing-scope.rs create mode 100644 src/test/ui/on-unimplemented/enclosing-scope.stderr create mode 100644 src/test/ui/on-unimplemented/feature-gate-on-unimplemented.rs rename src/test/ui/{feature-gates => on-unimplemented}/feature-gate-on-unimplemented.stderr (57%) create mode 100644 src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs create mode 100644 src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr create mode 100644 src/test/ui/or-patterns/exhaustiveness-pass.rs create mode 100644 src/test/ui/or-patterns/exhaustiveness-pass.stderr create mode 100644 src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs create mode 100644 src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr create mode 100644 src/test/ui/parser/extern-abi-from-mac-literal-frag.rs create mode 100644 src/test/ui/parser/extern-abi-raw-strings.rs create mode 100644 src/test/ui/parser/extern-abi-string-escaping.rs create mode 100644 src/test/ui/parser/extern-abi-syntactic.rs create mode 100644 src/test/ui/parser/issue-58094-missing-right-square-bracket.rs create mode 100644 src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr create mode 100644 src/test/ui/parser/issue-62524.rs create mode 100644 src/test/ui/parser/issue-62524.stderr create mode 100644 src/test/ui/parser/issue-63116.rs create mode 100644 src/test/ui/parser/issue-63116.stderr create mode 100644 src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs create mode 100644 src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs create mode 100644 src/test/ui/parser/issue-65846-rollback-gating-failing-matcher.rs create mode 100644 src/test/ui/parser/lifetime-in-pattern-recover.rs create mode 100644 src/test/ui/parser/lifetime-in-pattern-recover.stderr create mode 100644 src/test/ui/parser/mbe_missing_right_paren.rs create mode 100644 src/test/ui/parser/mbe_missing_right_paren.stderr create mode 100644 src/test/ui/parser/missing_right_paren.rs create mode 100644 src/test/ui/parser/missing_right_paren.stderr create mode 100644 src/test/ui/pathless-extern-ok.rs create mode 100644 src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs create mode 100644 src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs create mode 100644 src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs create mode 100644 src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr create mode 100644 src/test/ui/pattern/usefulness/match-empty.rs create mode 100644 src/test/ui/pattern/usefulness/match-empty.stderr rename src/test/ui/pattern/{ => usefulness}/slice-pattern-const-2.rs (100%) rename src/test/ui/pattern/{ => usefulness}/slice-pattern-const-2.stderr (100%) rename src/test/ui/pattern/{ => usefulness}/slice-pattern-const-3.rs (100%) rename src/test/ui/pattern/{ => usefulness}/slice-pattern-const-3.stderr (100%) rename src/test/ui/pattern/{ => usefulness}/slice-pattern-const.rs (88%) rename src/test/ui/pattern/{ => usefulness}/slice-pattern-const.stderr (87%) create mode 100644 src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs create mode 100644 src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr create mode 100644 src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs create mode 100644 src/test/ui/pattern/usefulness/slice-patterns-reachability.rs create mode 100644 src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr create mode 100644 src/test/ui/pattern/usefulness/top-level-alternation.rs create mode 100644 src/test/ui/pattern/usefulness/top-level-alternation.stderr create mode 100644 src/test/ui/print_type_sizes/zero-sized-fields.rs create mode 100644 src/test/ui/print_type_sizes/zero-sized-fields.stdout create mode 100644 src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs create mode 100644 src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs create mode 100644 src/test/ui/proc-macro/derive-helper-shadowing-2.rs create mode 100644 src/test/ui/raw-ref-op/feature-raw-ref-op.rs create mode 100644 src/test/ui/raw-ref-op/feature-raw-ref-op.stderr create mode 100644 src/test/ui/raw-ref-op/raw-ref-op.rs create mode 100644 src/test/ui/raw-ref-op/raw-ref-op.stderr create mode 100644 src/test/ui/raw-ref-op/raw-ref-temp-deref.rs create mode 100644 src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr create mode 100644 src/test/ui/raw-ref-op/raw-ref-temp.rs create mode 100644 src/test/ui/raw-ref-op/raw-ref-temp.stderr create mode 100644 src/test/ui/raw-ref-op/unusual_locations.rs create mode 100644 src/test/ui/raw-ref-op/unusual_locations.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/const-caller-location.rs create mode 100644 src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/pass.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs create mode 100644 src/test/ui/sanitize-cfg.rs create mode 100644 src/test/ui/self/arbitrary_self_types_nested.rs rename src/test/ui/span/{unused-warning-point-at-signature.rs => unused-warning-point-at-identifier.rs} (84%) rename src/test/ui/span/{unused-warning-point-at-signature.stderr => unused-warning-point-at-identifier.stderr} (52%) create mode 100644 src/test/ui/suggestions/missing-trait-item.fixed create mode 100644 src/test/ui/suggestions/missing-trait-item.rs create mode 100644 src/test/ui/suggestions/missing-trait-item.stderr create mode 100644 src/test/ui/suggestions/option-content-move2.rs create mode 100644 src/test/ui/suggestions/option-content-move2.stderr create mode 100644 src/test/ui/suggestions/raw-name-use-suggestion.rs create mode 100644 src/test/ui/suggestions/raw-name-use-suggestion.stderr create mode 100644 src/test/ui/suggestions/type-ascription-instead-of-path-2.rs create mode 100644 src/test/ui/suggestions/type-ascription-instead-of-path-2.stderr create mode 100644 src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs create mode 100644 src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr create mode 100644 src/test/ui/traits/auxiliary/crate_a2.rs create mode 100644 src/test/ui/traits/trait-bounds-same-crate-name.rs create mode 100644 src/test/ui/traits/trait-bounds-same-crate-name.stderr create mode 100644 src/test/ui/type-alias-impl-trait/assoc-type-const.rs create mode 100644 src/test/ui/type-alias-impl-trait/assoc-type-const.stderr create mode 100644 src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs create mode 100644 src/test/ui/type-alias-impl-trait/fallback.rs delete mode 100644 src/test/ui/type-alias-impl-trait/issue-58887.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-63263-closure-return.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-63279.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-63279.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs create mode 100644 src/test/ui/type-inference/or_else-multiple-type-params.rs create mode 100644 src/test/ui/type-inference/or_else-multiple-type-params.stderr create mode 100644 src/test/ui/type-inference/sort_by_key.rs create mode 100644 src/test/ui/type-inference/sort_by_key.stderr create mode 100644 src/test/ui/type-inference/unbounded-associated-type.rs create mode 100644 src/test/ui/type-inference/unbounded-associated-type.stderr create mode 100644 src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs create mode 100644 src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr create mode 100644 src/test/ui/type-inference/unbounded-type-param-in-fn.rs create mode 100644 src/test/ui/type-inference/unbounded-type-param-in-fn.stderr create mode 100644 src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs create mode 100644 src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr create mode 100644 src/test/ui/type/type-error-break-tail.rs create mode 100644 src/test/ui/type/type-error-break-tail.stderr create mode 100644 src/test/ui/unboxed-closures/issue-30906.nll.stderr create mode 100644 src/test/ui/unboxed-closures/issue-30906.rs create mode 100644 src/test/ui/unboxed-closures/issue-30906.stderr rename src/test/ui/{dead-code-ret.rs => unreachable-code-ret.rs} (100%) rename src/test/ui/{dead-code-ret.stderr => unreachable-code-ret.stderr} (86%) create mode 100644 src/test/ui/unsized/unsized-fn-param.rs create mode 100644 src/test/ui/unsized/unsized-fn-param.stderr create mode 100644 vendor/cc/Cargo.lock delete mode 100644 vendor/cc/azure-pipelines.yml delete mode 100644 vendor/cc/ci/azure-install-rust.yml delete mode 100644 vendor/cc/ci/azure-steps.yml create mode 100644 vendor/cc/tests/cflags.rs create mode 100644 vendor/cc/tests/cxxflags.rs create mode 100644 vendor/codespan-reporting/.cargo-checksum.json create mode 100644 vendor/codespan-reporting/Cargo.lock create mode 100644 vendor/codespan-reporting/Cargo.toml create mode 100644 vendor/codespan-reporting/README.md create mode 100644 vendor/codespan-reporting/examples/term.rs create mode 100644 vendor/codespan-reporting/src/diagnostic.rs create mode 100644 vendor/codespan-reporting/src/lib.rs create mode 100644 vendor/codespan-reporting/src/term/config.rs create mode 100644 vendor/codespan-reporting/src/term/mod.rs create mode 100644 vendor/codespan-reporting/src/term/views/diagnostic.rs create mode 100644 vendor/codespan-reporting/src/term/views/header.rs create mode 100644 vendor/codespan-reporting/src/term/views/locus.rs create mode 100644 vendor/codespan-reporting/src/term/views/mod.rs create mode 100644 vendor/codespan-reporting/src/term/views/new_line.rs create mode 100644 vendor/codespan-reporting/src/term/views/source_snippet/border.rs create mode 100644 vendor/codespan-reporting/src/term/views/source_snippet/gutter.rs create mode 100644 vendor/codespan-reporting/src/term/views/source_snippet/mod.rs create mode 100644 vendor/codespan-reporting/src/term/views/source_snippet/note.rs create mode 100644 vendor/codespan-reporting/src/term/views/source_snippet/underline.rs create mode 100644 vendor/codespan-reporting/tests/snapshots/empty_spans__rich_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/empty_spans__rich_no_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/fizz_buzz__rich_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/fizz_buzz__rich_no_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/fizz_buzz__short_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/fizz_buzz__short_no_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/multifile__rich_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/multifile__rich_no_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/multifile__short_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/multifile__short_no_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/tabbed__tab_width_3_no_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/tabbed__tab_width_6_no_color.snap create mode 100644 vendor/codespan-reporting/tests/snapshots/tabbed__tab_width_default_no_color.snap create mode 100644 vendor/codespan-reporting/tests/support/color_buffer.rs create mode 100644 vendor/codespan-reporting/tests/support/mod.rs create mode 100644 vendor/codespan-reporting/tests/term.rs create mode 100644 vendor/codespan/.cargo-checksum.json create mode 100644 vendor/codespan/Cargo.toml create mode 100644 vendor/codespan/src/file.rs create mode 100644 vendor/codespan/src/index.rs create mode 100644 vendor/codespan/src/lib.rs create mode 100644 vendor/codespan/src/location.rs create mode 100644 vendor/codespan/src/span.rs create mode 100644 vendor/compiler_builtins/libm/src/math/nextafter.rs create mode 100644 vendor/compiler_builtins/libm/src/math/nextafterf.rs create mode 100644 vendor/compiler_builtins/libm/src/math/remainder.rs create mode 100644 vendor/compiler_builtins/libm/src/math/remainderf.rs rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/.cargo-checksum.json (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/CHANGELOG.md (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/Cargo.toml (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/LICENSE-APACHE (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/LICENSE-MIT (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/README.md (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/benches/atomic_cell.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/atomic/atomic_cell.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/atomic/consume.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/atomic/mod.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/backoff.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/cache_padded.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/lib.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/sync/mod.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/sync/parker.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/sync/sharded_lock.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/sync/wait_group.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/src/thread.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/tests/atomic_cell.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/tests/cache_padded.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/tests/parker.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/tests/sharded_lock.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/tests/thread.rs (100%) rename vendor/{crossbeam-utils => crossbeam-utils-0.6.5}/tests/wait_group.rs (100%) create mode 100644 vendor/flate2/Cargo.lock delete mode 100644 vendor/flate2/appveyor.yml delete mode 100644 vendor/flate2/src/ffi.rs create mode 100644 vendor/flate2/src/ffi/c.rs create mode 100644 vendor/flate2/src/ffi/mod.rs create mode 100644 vendor/flate2/src/ffi/rust.rs create mode 100644 vendor/flate2/tests/async-reader.rs create mode 100644 vendor/idna-0.1.5/.cargo-checksum.json rename vendor/{percent-encoding-1.0.1 => idna-0.1.5}/Cargo.toml (61%) rename vendor/{percent-encoding-1.0.1 => idna-0.1.5}/LICENSE-APACHE (100%) rename vendor/{percent-encoding-1.0.1 => idna-0.1.5}/LICENSE-MIT (100%) create mode 100644 vendor/idna-0.1.5/src/IdnaMappingTable.txt create mode 100644 vendor/idna-0.1.5/src/lib.rs create mode 100644 vendor/idna-0.1.5/src/make_uts46_mapping_table.py create mode 100644 vendor/idna-0.1.5/src/punycode.rs create mode 100644 vendor/idna-0.1.5/src/uts46.rs create mode 100644 vendor/idna-0.1.5/src/uts46_mapping_table.rs create mode 100644 vendor/idna-0.1.5/tests/IdnaTest.txt create mode 100644 vendor/idna-0.1.5/tests/punycode.rs create mode 100644 vendor/idna-0.1.5/tests/punycode_tests.json create mode 100644 vendor/idna-0.1.5/tests/tests.rs create mode 100644 vendor/idna-0.1.5/tests/unit.rs create mode 100644 vendor/idna-0.1.5/tests/uts46.rs create mode 100644 vendor/itertools-0.7.8/.cargo-checksum.json create mode 100644 vendor/itertools-0.7.8/Cargo.toml rename vendor/{version_check => itertools-0.7.8}/LICENSE-APACHE (100%) create mode 100644 vendor/itertools-0.7.8/LICENSE-MIT create mode 100644 vendor/itertools-0.7.8/Makefile create mode 100644 vendor/itertools-0.7.8/README.rst create mode 100644 vendor/itertools-0.7.8/benches/bench1.rs create mode 100644 vendor/itertools-0.7.8/benches/extra/mod.rs create mode 100644 vendor/itertools-0.7.8/benches/extra/zipslices.rs create mode 100644 vendor/itertools-0.7.8/benches/tree_fold1.rs create mode 100644 vendor/itertools-0.7.8/benches/tuple_combinations.rs create mode 100644 vendor/itertools-0.7.8/benches/tuples.rs create mode 100644 vendor/itertools-0.7.8/bors.toml create mode 100644 vendor/itertools-0.7.8/custom.css create mode 100644 vendor/itertools-0.7.8/examples/iris.data create mode 100644 vendor/itertools-0.7.8/examples/iris.rs create mode 100644 vendor/itertools-0.7.8/src/adaptors/mod.rs create mode 100644 vendor/itertools-0.7.8/src/adaptors/multi_product.rs create mode 100644 vendor/itertools-0.7.8/src/combinations.rs create mode 100644 vendor/itertools-0.7.8/src/concat_impl.rs create mode 100644 vendor/itertools-0.7.8/src/cons_tuples_impl.rs create mode 100644 vendor/itertools-0.7.8/src/diff.rs create mode 100644 vendor/itertools-0.7.8/src/either_or_both.rs create mode 100644 vendor/itertools-0.7.8/src/format.rs create mode 100644 vendor/itertools-0.7.8/src/free.rs create mode 100644 vendor/itertools-0.7.8/src/group_map.rs create mode 100644 vendor/itertools-0.7.8/src/groupbylazy.rs create mode 100644 vendor/itertools-0.7.8/src/impl_macros.rs create mode 100644 vendor/itertools-0.7.8/src/intersperse.rs create mode 100644 vendor/itertools-0.7.8/src/kmerge_impl.rs create mode 100644 vendor/itertools-0.7.8/src/lib.rs create mode 100644 vendor/itertools-0.7.8/src/merge_join.rs create mode 100644 vendor/itertools-0.7.8/src/minmax.rs create mode 100644 vendor/itertools-0.7.8/src/multipeek_impl.rs create mode 100644 vendor/itertools-0.7.8/src/pad_tail.rs create mode 100644 vendor/itertools-0.7.8/src/peeking_take_while.rs create mode 100644 vendor/itertools-0.7.8/src/process_results_impl.rs create mode 100644 vendor/itertools-0.7.8/src/put_back_n_impl.rs create mode 100644 vendor/itertools-0.7.8/src/rciter_impl.rs create mode 100644 vendor/itertools-0.7.8/src/repeatn.rs create mode 100644 vendor/itertools-0.7.8/src/size_hint.rs create mode 100644 vendor/itertools-0.7.8/src/sources.rs create mode 100644 vendor/itertools-0.7.8/src/tee.rs create mode 100644 vendor/itertools-0.7.8/src/tuple_impl.rs create mode 100644 vendor/itertools-0.7.8/src/unique_impl.rs create mode 100644 vendor/itertools-0.7.8/src/with_position.rs create mode 100644 vendor/itertools-0.7.8/src/zip_eq_impl.rs create mode 100644 vendor/itertools-0.7.8/src/zip_longest.rs create mode 100644 vendor/itertools-0.7.8/src/ziptuple.rs create mode 100644 vendor/itertools-0.7.8/tests/merge_join.rs create mode 100644 vendor/itertools-0.7.8/tests/peeking_take_while.rs create mode 100644 vendor/itertools-0.7.8/tests/quick.rs create mode 100644 vendor/itertools-0.7.8/tests/test_core.rs create mode 100644 vendor/itertools-0.7.8/tests/test_std.rs create mode 100644 vendor/itertools-0.7.8/tests/tuples.rs create mode 100644 vendor/itertools-0.7.8/tests/zip.rs delete mode 100644 vendor/measureme/benches/serialization_bench.rs delete mode 100644 vendor/measureme/src/event.rs delete mode 100644 vendor/measureme/src/profiling_data.rs delete mode 100644 vendor/measureme/src/testing_common.rs delete mode 100644 vendor/measureme/tests/serialization.rs delete mode 100644 vendor/memoffset-0.2.1/.cargo-checksum.json delete mode 100644 vendor/memoffset-0.2.1/Cargo.toml delete mode 100644 vendor/memoffset-0.2.1/LICENSE delete mode 100644 vendor/memoffset-0.2.1/README.md delete mode 100644 vendor/memoffset-0.2.1/src/lib.rs delete mode 100644 vendor/memoffset-0.2.1/src/offset_of.rs delete mode 100644 vendor/memoffset-0.2.1/src/span_of.rs create mode 100644 vendor/num_cpus/examples/values.rs delete mode 100644 vendor/percent-encoding-1.0.1/.cargo-checksum.json delete mode 100644 vendor/percent-encoding-1.0.1/lib.rs delete mode 100644 vendor/polonius-engine/src/output/hybrid.rs create mode 100644 vendor/rand_core-0.4.0/.cargo-checksum.json create mode 100644 vendor/rand_core-0.4.0/CHANGELOG.md create mode 100644 vendor/rand_core-0.4.0/COPYRIGHT create mode 100644 vendor/rand_core-0.4.0/Cargo.toml create mode 100644 vendor/rand_core-0.4.0/LICENSE-APACHE create mode 100644 vendor/rand_core-0.4.0/LICENSE-MIT create mode 100644 vendor/rand_core-0.4.0/README.md create mode 100644 vendor/rand_core-0.4.0/src/block.rs create mode 100644 vendor/rand_core-0.4.0/src/error.rs create mode 100644 vendor/rand_core-0.4.0/src/impls.rs create mode 100644 vendor/rand_core-0.4.0/src/le.rs create mode 100644 vendor/rand_core-0.4.0/src/lib.rs create mode 100644 vendor/rand_core/src/os.rs create mode 100644 vendor/smallvec-0.6.10/.cargo-checksum.json create mode 100644 vendor/smallvec-0.6.10/Cargo.toml create mode 100644 vendor/smallvec-0.6.10/LICENSE-APACHE create mode 100644 vendor/smallvec-0.6.10/LICENSE-MIT create mode 100644 vendor/smallvec-0.6.10/README.md create mode 100644 vendor/smallvec-0.6.10/benches/bench.rs create mode 100644 vendor/smallvec-0.6.10/lib.rs create mode 100644 vendor/smallvec/scripts/run_miri.sh create mode 100644 vendor/smallvec/specialization.rs delete mode 100755 vendor/syn/tests/clone.sh mode change 100644 => 100755 vendor/syn/tests/repo/mod.rs create mode 100644 vendor/syn/tests/test_receiver.rs mode change 100644 => 100755 vendor/syn/tests/test_round_trip.rs create mode 100644 vendor/syn/tests/test_visibility.rs create mode 100644 vendor/unicode-segmentation/src/sentence.rs rename vendor/{version_check => version_check-0.1.5}/.cargo-checksum.json (100%) rename vendor/{version_check => version_check-0.1.5}/Cargo.toml (100%) create mode 100644 vendor/version_check-0.1.5/LICENSE-APACHE rename vendor/{version_check => version_check-0.1.5}/LICENSE-MIT (100%) rename vendor/{version_check => version_check-0.1.5}/README.md (100%) rename vendor/{version_check => version_check-0.1.5}/src/lib.rs (100%) create mode 100644 vendor/wasi-0.7.0/.cargo-checksum.json rename vendor/{wasi => wasi-0.7.0}/0001-maybe.patch (100%) create mode 100644 vendor/wasi-0.7.0/CODE_OF_CONDUCT.md create mode 100644 vendor/wasi-0.7.0/CONTRIBUTING.md create mode 100644 vendor/wasi-0.7.0/Cargo.toml create mode 100644 vendor/wasi-0.7.0/LICENSE-APACHE create mode 100644 vendor/wasi-0.7.0/LICENSE-Apache-2.0_WITH_LLVM-exception create mode 100644 vendor/wasi-0.7.0/LICENSE-MIT create mode 100644 vendor/wasi-0.7.0/README.md rename vendor/{wasi => wasi-0.7.0}/clip.log (100%) create mode 100644 vendor/wasi-0.7.0/old-bitflags.patch rename vendor/{wasi => wasi-0.7.0}/rusty-tags.vi (100%) create mode 100644 vendor/wasi-0.7.0/src/lib.rs rename vendor/{wasi => wasi-0.7.0}/src/wasi_unstable/mod.rs (100%) rename vendor/{wasi => wasi-0.7.0}/src/wasi_unstable/raw.rs (100%) create mode 100644 vendor/wasi/ORG_CODE_OF_CONDUCT.md create mode 100644 vendor/wasi/SECURITY.md create mode 100644 vendor/wasi/src/error.rs create mode 100644 vendor/wasi/src/lib_generated.rs create mode 100644 vendor/winapi/src/km/d3dkmthk.rs create mode 100644 vendor/winapi/src/km/mod.rs create mode 100644 vendor/winapi/src/shared/bthdef.rs create mode 100644 vendor/winapi/src/shared/bthioctl.rs create mode 100644 vendor/winapi/src/shared/bthsdpdef.rs create mode 100644 vendor/winapi/src/shared/d3dkmdt.rs create mode 100644 vendor/winapi/src/shared/d3dukmdt.rs create mode 100644 vendor/winapi/src/shared/ifdef.rs create mode 100644 vendor/winapi/src/shared/mswsockdef.rs create mode 100644 vendor/winapi/src/shared/netioapi.rs create mode 100644 vendor/winapi/src/um/bluetoothapis.rs create mode 100644 vendor/winapi/src/um/bluetoothleapis.rs create mode 100644 vendor/winapi/src/um/bthledef.rs create mode 100644 vendor/winapi/src/um/dispex.rs create mode 100644 vendor/winapi/src/um/enclaveapi.rs create mode 100644 vendor/winapi/src/um/functiondiscoverykeys_devpkey.rs create mode 100644 vendor/winapi/src/um/mswsock.rs create mode 100644 vendor/winapi/src/um/portabledevice.rs create mode 100644 vendor/winapi/src/um/portabledeviceapi.rs create mode 100644 vendor/winapi/src/um/portabledevicetypes.rs create mode 100644 vendor/winapi/src/um/propkey.rs create mode 100644 vendor/winapi/src/um/spellcheck.rs create mode 100644 vendor/winapi/src/um/taskschd.rs create mode 100644 vendor/winapi/src/um/wbemads.rs create mode 100644 vendor/winapi/src/um/wbemcli.rs create mode 100644 vendor/winapi/src/um/wbemdisp.rs create mode 100644 vendor/winapi/src/um/wbemprov.rs create mode 100644 vendor/winapi/src/um/wbemtran.rs create mode 100644 vendor/winapi/src/um/wincontypes.rs create mode 100644 vendor/winapi/src/um/wpdmtpextensions.rs create mode 100644 vendor/winapi/src/um/ws2bth.rs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 37a217d2a0..8fbbd7c4a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -105,7 +105,7 @@ contributions to the compiler and the standard library. It also lists some really useful commands to the build system (`./x.py`), which could save you a lot of time. -[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html +[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html ## Pull Requests [pull-requests]: #pull-requests @@ -150,13 +150,13 @@ All pull requests are reviewed by another person. We have a bot, request. If you want to request that a specific person reviews your pull request, -you can add an `r?` to the message. For example, [Steve][steveklabnik] usually reviews +you can add an `r?` to the pull request description. For example, [Steve][steveklabnik] usually reviews documentation changes. So if you were to make a documentation change, add r? @steveklabnik -to the end of the message, and @rust-highfive will assign [@steveklabnik][steveklabnik] instead -of a random person. This is entirely optional. +to the end of the pull request description, and [@rust-highfive][rust-highfive] will assign +[@steveklabnik][steveklabnik] instead of a random person. This is entirely optional. After someone has reviewed your pull request, they will leave an annotation on the pull request with an `r+`. It will look something like this: diff --git a/Cargo.lock b/Cargo.lock index f44ed3d07f..1af0442dde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,7 +54,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -68,7 +68,7 @@ name = "arena" version = "0.0.0" dependencies = [ "rustc_data_structures", - "smallvec", + "smallvec 1.0.0", ] [[package]] @@ -104,7 +104,7 @@ checksum = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" dependencies = [ "libc", "termion", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -139,12 +139,30 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +dependencies = [ + "byteorder", +] + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitmaps" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" +dependencies = [ + "typenum", +] + [[package]] name = "blake2-rfc" version = "0.2.18" @@ -199,15 +217,10 @@ name = "build-manifest" version = "0.1.0" dependencies = [ "serde", + "serde_json", "toml", ] -[[package]] -name = "build_const" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" - [[package]] name = "build_helper" version = "0.1.0" @@ -240,6 +253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" dependencies = [ "byteorder", + "either", "iovec", ] @@ -261,7 +275,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.41.0" +version = "0.42.0" dependencies = [ "atty", "bytesize", @@ -269,9 +283,9 @@ dependencies = [ "cargo-test-macro", "cargo-test-support", "clap", - "core-foundation", + "core-foundation 0.7.0", "crates-io", - "crossbeam-utils 0.6.5", + "crossbeam-utils 0.7.0", "crypto-hash", "curl", "curl-sys", @@ -300,7 +314,7 @@ dependencies = [ "num_cpus", "opener", "openssl", - "percent-encoding 2.0.0", + "percent-encoding 2.1.0", "pretty_env_logger", "remove_dir_all", "rustc-workspace-hack", @@ -319,7 +333,7 @@ dependencies = [ "unicode-width", "url 2.1.0", "walkdir", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -381,9 +395,13 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.37" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" +checksum = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" +dependencies = [ + "jobserver", + "num_cpus", +] [[package]] name = "cfg-if" @@ -450,12 +468,15 @@ dependencies = [ "clippy_lints", "compiletest_rs", "derive-new", + "git2", "lazy_static 1.3.0", "regex", "rustc-workspace-hack", "rustc_tools_util 0.2.0", "semver", "serde", + "tempfile", + "tester", ] [[package]] @@ -476,7 +497,7 @@ dependencies = [ "regex-syntax", "semver", "serde", - "smallvec", + "smallvec 1.0.0", "toml", "unicode-normalization", "url 2.1.0", @@ -500,6 +521,26 @@ dependencies = [ "cc", ] +[[package]] +name = "codespan" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de67bdcd653002a6dba3eb53850ce3a485547225d81cb6c2bbdbc5a0cba5d15d" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "codespan-reporting" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1d915d9e2b2ad696b2cd73215a84823ef3f0e3084d90304204415921b62c6" +dependencies = [ + "codespan", + "termcolor", + "unicode-width", +] + [[package]] name = "colored" version = "1.6.0" @@ -529,9 +570,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.18" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1c086a06d6f52f9c0d50cacdc021bfb6034ddeec9fb7e62f099f13f65472f4" +checksum = "e6f083abf9bb9005a27d2da62706f661245278cb7096da37ab27410eaf60f2c1" dependencies = [ "cc", "rustc-std-workspace-core", @@ -553,14 +594,14 @@ dependencies = [ "serde", "serde_json", "walkdir", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] name = "compiletest_rs" -version = "0.3.25" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75b10a18fb53549fdd090846eb01c7f8593914494d1faabc4d3005c436e417a" +checksum = "d7b678957210a00ba0fbeacc23d38cbfbf29895564da1616564634351e1dac5e" dependencies = [ "diff", "filetime", @@ -574,7 +615,8 @@ dependencies = [ "serde_derive", "serde_json", "tempfile", - "winapi 0.3.6", + "tester", + "winapi 0.3.8", ] [[package]] @@ -583,6 +625,34 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +[[package]] +name = "cookie" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" +dependencies = [ + "time", + "url 1.7.2", +] + +[[package]] +name = "cookie_store" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" +dependencies = [ + "cookie", + "failure", + "idna 0.1.5", + "log", + "publicsuffix", + "serde", + "serde_json", + "time", + "try_from", + "url 1.7.2", +] + [[package]] name = "core" version = "0.0.0" @@ -596,7 +666,17 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.6.2", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys 0.7.0", "libc", ] @@ -606,28 +686,25 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +[[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + [[package]] name = "crates-io" -version = "0.29.0" +version = "0.30.0" dependencies = [ "curl", "failure", - "percent-encoding 2.0.0", + "percent-encoding 2.1.0", "serde", "serde_derive", "serde_json", "url 2.1.0", ] -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -dependencies = [ - "build_const", -] - [[package]] name = "crc32fast" version = "1.1.2" @@ -644,17 +721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" dependencies = [ "crossbeam-utils 0.6.5", - "smallvec", -] - -[[package]] -name = "crossbeam-deque" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" -dependencies = [ - "crossbeam-epoch 0.3.1", - "crossbeam-utils 0.2.2", + "smallvec 0.6.10", ] [[package]] @@ -663,7 +730,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" dependencies = [ - "crossbeam-epoch 0.7.2", + "crossbeam-epoch", "crossbeam-utils 0.6.5", ] @@ -673,25 +740,10 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" dependencies = [ - "crossbeam-epoch 0.7.2", + "crossbeam-epoch", "crossbeam-utils 0.6.5", ] -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -dependencies = [ - "arrayvec", - "cfg-if", - "crossbeam-utils 0.2.2", - "lazy_static 1.3.0", - "memoffset 0.2.1", - "nodrop", - "scopeguard 0.3.3", -] - [[package]] name = "crossbeam-epoch" version = "0.7.2" @@ -702,7 +754,7 @@ dependencies = [ "cfg-if", "crossbeam-utils 0.6.5", "lazy_static 1.3.0", - "memoffset 0.5.1", + "memoffset", "scopeguard 1.0.0", ] @@ -717,19 +769,21 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.2.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" dependencies = [ "cfg-if", + "lazy_static 1.3.0", ] [[package]] name = "crossbeam-utils" -version = "0.6.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" dependencies = [ + "autocfg", "cfg-if", "lazy_static 1.3.0", ] @@ -743,7 +797,7 @@ dependencies = [ "commoncrypto", "hex 0.3.2", "openssl", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -758,7 +812,7 @@ dependencies = [ "openssl-sys", "schannel", "socket2", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -774,7 +828,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -890,7 +944,7 @@ dependencies = [ "cfg-if", "libc", "redox_users", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -904,6 +958,18 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "dtoa" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" + +[[package]] +name = "dunce" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0ad6bf6a88548d1126045c413548df1453d9be094a8ab9fd59bf1fdd338da4f" + [[package]] name = "either" version = "1.5.0" @@ -934,6 +1000,15 @@ dependencies = [ "log", ] +[[package]] +name = "encoding_rs" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_logger" version = "0.6.2" @@ -1024,15 +1099,15 @@ checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" [[package]] name = "flate2" -version = "1.0.6" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2291c165c8e703ee54ef3055ad6188e3d51108e2ded18e9f2476e774fc5ad3d4" +checksum = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" dependencies = [ + "cfg-if", "crc32fast", "libc", "libz-sys", - "miniz-sys", - "miniz_oxide_c_api", + "miniz_oxide", ] [[package]] @@ -1081,7 +1156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -1137,6 +1212,16 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +dependencies = [ + "futures", + "num_cpus", +] + [[package]] name = "fwdansi" version = "1.0.1" @@ -1175,14 +1260,14 @@ checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.7.0", ] [[package]] name = "git2" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327d698f86a7ebdfeb86a4238ccdb004828939d3a3555b6ead679541d14e36c0" +checksum = "39f27186fbb5ec67ece9a56990292bc5aed3c3fc51b9b07b0b52446b1dfb4a82" dependencies = [ "bitflags", "libc", @@ -1228,6 +1313,24 @@ dependencies = [ name = "graphviz" version = "0.0.0" +[[package]] +name = "h2" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392" +dependencies = [ + "byteorder", + "bytes", + "fnv", + "futures", + "http", + "indexmap", + "log", + "slab", + "string", + "tokio-io", +] + [[package]] name = "handlebars" version = "2.0.1" @@ -1305,7 +1408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8" dependencies = [ "scopeguard 1.0.0", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -1319,9 +1422,38 @@ dependencies = [ "markup5ever", "proc-macro2 1.0.3", "quote 1.0.2", - "syn 1.0.5", + "syn 1.0.11", +] + +[[package]] +name = "http" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf" +dependencies = [ + "bytes", + "fnv", + "itoa", ] +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +dependencies = [ + "bytes", + "futures", + "http", + "tokio-buf", +] + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" + [[package]] name = "humantime" version = "1.3.0" @@ -1331,6 +1463,49 @@ dependencies = [ "quick-error", ] +[[package]] +name = "hyper" +version = "0.12.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6481fff8269772d4463253ca83c788104a7305cb3fb9136bc651a6211e46e03f" +dependencies = [ + "bytes", + "futures", + "futures-cpupool", + "h2", + "http", + "http-body", + "httparse", + "iovec", + "itoa", + "log", + "net2", + "rustc_version", + "time", + "tokio", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +dependencies = [ + "bytes", + "futures", + "hyper", + "native-tls", + "tokio-io", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1385,13 +1560,16 @@ dependencies = [ [[package]] name = "im-rc" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0197597d095c0d11107975d3175173f810ee572c2501ff4de64f4f3f119806" +checksum = "e9ad726dce25993be6352b0bff048e4d2647440c0a673d32257c4fac49356d18" dependencies = [ - "rustc_version", + "bitmaps", + "rand_core 0.5.1", + "rand_xoshiro", "sized-chunks", "typenum", + "version_check 0.9.1", ] [[package]] @@ -1413,7 +1591,7 @@ dependencies = [ "remove_dir_all", "tar", "walkdir", - "winapi 0.3.6", + "winapi 0.3.8", "xz2", ] @@ -1620,9 +1798,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2078aec6f4b16d1b89f6a72e4f6eb1e75ffa85312023291e89c6d3087bc8fb" +checksum = "a30f8637eb59616ee3b8a00f6adff781ee4ddd8343a615b8238de756060cc1b3" dependencies = [ "cc", "libc", @@ -1814,14 +1992,42 @@ dependencies = [ "toml-query", ] +[[package]] +name = "mdbook-linkcheck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0a04db564ca37c47771f8455c825dc941ea851ff0deffcf55a04c512406b409" +dependencies = [ + "codespan", + "codespan-reporting", + "dunce", + "either", + "env_logger 0.7.1", + "failure", + "http", + "log", + "mdbook", + "percent-encoding 2.1.0", + "pulldown-cmark 0.6.1", + "rayon", + "regex", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "structopt", +] + [[package]] name = "measureme" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd21b0e6e1af976b269ce062038fe5e1b9ca2f817ab7a3af09ec4210aebf0d30" +checksum = "c420bbc064623934620b5ab2dc0cf96451b34163329e82f95e7fa1b7b99a6ac8" dependencies = [ "byteorder", "memmap", + "parking_lot 0.9.0", "rustc-hash", ] @@ -1833,20 +2039,14 @@ checksum = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" [[package]] name = "memmap" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" +checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" dependencies = [ "libc", - "winapi 0.3.6", + "winapi 0.3.8", ] -[[package]] -name = "memoffset" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" - [[package]] name = "memoffset" version = "0.5.1" @@ -1857,43 +2057,40 @@ dependencies = [ ] [[package]] -name = "minifier" -version = "0.0.33" +name = "mime" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332" +checksum = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" dependencies = [ - "macro-utils", + "unicase", ] [[package]] -name = "miniz-sys" -version = "0.1.11" +name = "mime_guess" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" +checksum = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" dependencies = [ - "cc", - "libc", + "mime", + "unicase", ] [[package]] -name = "miniz_oxide" -version = "0.2.0" +name = "minifier" +version = "0.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" +checksum = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332" dependencies = [ - "adler32", + "macro-utils", ] [[package]] -name = "miniz_oxide_c_api" -version = "0.2.0" +name = "miniz_oxide" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" +checksum = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" dependencies = [ - "cc", - "crc", - "libc", - "miniz_oxide", + "adler32", ] [[package]] @@ -1924,7 +2121,7 @@ dependencies = [ "log", "mio", "miow 0.3.3", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -1957,7 +2154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" dependencies = [ "socket2", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -1977,10 +2174,29 @@ dependencies = [ "rand 0.7.0", "rustc-workspace-hack", "rustc_version", + "serde", "shell-escape", "vergen", ] +[[package]] +name = "native-tls" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" +dependencies = [ + "lazy_static 1.3.0", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "net2" version = "0.2.33" @@ -1989,7 +2205,7 @@ checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" dependencies = [ "cfg-if", "libc", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -2021,9 +2237,9 @@ checksum = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" dependencies = [ "libc", ] @@ -2046,14 +2262,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "998c59e83d9474c01127a96e023b7a04bb061dd286bf8bb939d31dc8d31a7448" dependencies = [ - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] name = "openssl" -version = "0.10.16" +version = "0.10.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" +checksum = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" dependencies = [ "bitflags", "cfg-if", @@ -2080,15 +2296,15 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.43" +version = "0.9.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" +checksum = "c977d08e1312e2f7e4b86f9ebaa0ed3b19d1daff75fae88bbb88108afbd801fc" dependencies = [ + "autocfg", "cc", "libc", "openssl-src", "pkg-config", - "rustc_version", "vcpkg", ] @@ -2158,7 +2374,7 @@ dependencies = [ "tokio", "tokio-named-pipes", "tokio-uds", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -2191,8 +2407,8 @@ dependencies = [ "libc", "rand 0.6.1", "rustc_version", - "smallvec", - "winapi 0.3.6", + "smallvec 0.6.10", + "winapi 0.3.8", ] [[package]] @@ -2206,8 +2422,8 @@ dependencies = [ "libc", "redox_syscall", "rustc_version", - "smallvec", - "winapi 0.3.6", + "smallvec 0.6.10", + "winapi 0.3.8", ] [[package]] @@ -2218,9 +2434,9 @@ checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f28a6faf4ffea762ba8f4baef48c61a6db348647c73095034041fc79dd954" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pest" @@ -2321,9 +2537,9 @@ checksum = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" [[package]] name = "polonius-engine" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50fa9dbfd0d3d60594da338cfe6f94028433eecae4b11b7e83fd99759227bbfe" +checksum = "1e478d7c38eb785c6416cbe58df12aa55d7aefa3759b6d3e044b2ed03f423cec" dependencies = [ "datafrog", "log", @@ -2380,7 +2596,7 @@ checksum = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", - "syn 1.0.5", + "syn 1.0.11", ] [[package]] @@ -2417,6 +2633,19 @@ dependencies = [ "core", ] +[[package]] +name = "publicsuffix" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" +dependencies = [ + "error-chain", + "idna 0.2.0", + "lazy_static 1.3.0", + "regex", + "url 2.1.0", +] + [[package]] name = "pulldown-cmark" version = "0.5.3" @@ -2478,9 +2707,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.28" +version = "2.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc70369054bad4ad0c16a3f45cd73e0695361a3af35c7b465e619ac2674f064" +checksum = "7a6d7ffceb4da3e0a29c18986f0469c209f4db3ab9f2ffe286eaa1104a3e5028" dependencies = [ "bitflags", "clap", @@ -2509,7 +2738,7 @@ dependencies = [ "rand_pcg", "rand_xorshift 0.1.0", "rustc_version", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -2521,7 +2750,7 @@ dependencies = [ "getrandom", "libc", "rand_chacha 0.2.1", - "rand_core 0.5.0", + "rand_core 0.5.1", "rand_hc 0.2.0", ] @@ -2542,7 +2771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" dependencies = [ "c2-chacha", - "rand_core 0.5.0", + "rand_core 0.5.1", ] [[package]] @@ -2559,9 +2788,9 @@ checksum = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" [[package]] name = "rand_core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ "getrandom", ] @@ -2581,7 +2810,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.0", + "rand_core 0.5.1", ] [[package]] @@ -2604,7 +2833,7 @@ dependencies = [ "libc", "rand_core 0.4.0", "rdrand", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -2632,7 +2861,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" dependencies = [ - "rand_core 0.5.0", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xoshiro" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -2731,12 +2969,46 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" dependencies = [ - "winapi 0.3.6", + "winapi 0.3.8", +] + +[[package]] +name = "reqwest" +version = "0.9.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c2064233e442ce85c77231ebd67d9eca395207dec2127fe0bbedde4bd29a650" +dependencies = [ + "base64", + "bytes", + "cookie", + "cookie_store", + "encoding_rs", + "flate2", + "futures", + "http", + "hyper", + "hyper-tls", + "log", + "mime", + "mime_guess", + "native-tls", + "serde", + "serde_json", + "serde_urlencoded", + "time", + "tokio", + "tokio-executor", + "tokio-io", + "tokio-threadpool", + "tokio-timer", + "url 1.7.2", + "uuid", + "winreg", ] [[package]] name = "rls" -version = "1.40.0" +version = "1.41.0" dependencies = [ "cargo", "cargo_metadata 0.8.0", @@ -2861,8 +3133,10 @@ name = "rustbook" version = "0.1.0" dependencies = [ "clap", + "codespan-reporting", "failure", "mdbook", + "mdbook-linkcheck", "rustc-workspace-hack", ] @@ -2874,7 +3148,6 @@ dependencies = [ "backtrace", "bitflags", "byteorder", - "cc", "chalk-engine", "fmt_macros", "graphviz", @@ -2884,43 +3157,46 @@ dependencies = [ "num_cpus", "parking_lot 0.9.0", "polonius-engine", - "rustc-rayon 0.3.0", - "rustc-rayon-core 0.3.0", + "rustc-rayon", + "rustc-rayon-core", "rustc_apfloat", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", + "rustc_feature", "rustc_fs_util", "rustc_index", "rustc_macros", + "rustc_session", "rustc_target", "scoped-tls", "serialize", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_pos", ] [[package]] name = "rustc-ap-arena" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009" +checksum = "7475f4c707269b56eb7144c53591e3cd6369a5aa1d66434829ea11df96d5e7e3" dependencies = [ "rustc-ap-rustc_data_structures", - "smallvec", + "smallvec 0.6.10", ] [[package]] name = "rustc-ap-graphviz" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee549ade784b444ef10c0240c3487ed785aa65d711071f7984246b15329a17b6" +checksum = "6e59a55520f140a70a3e0fad80a36e807caa85e9d7016167b91a5b521ea929be" [[package]] name = "rustc-ap-rustc_data_structures" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca545744a5a9b42e3d0410d6290d40de96dd567253fe77f310c1de4afd213dd4" +checksum = "6420857d5a088f680ec1ba736ffba4ee9c1964b0d397e6318f38d461f4f7d5cb" dependencies = [ "cfg-if", "crossbeam-utils 0.6.5", @@ -2934,17 +3210,17 @@ dependencies = [ "rustc-ap-rustc_index", "rustc-ap-serialize", "rustc-hash", - "rustc-rayon 0.2.0", - "rustc-rayon-core 0.2.0", - "smallvec", + "rustc-rayon", + "rustc-rayon-core", + "smallvec 0.6.10", "stable_deref_trait", ] [[package]] name = "rustc-ap-rustc_errors" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6967a41ed38ef4bce0f559fe9a4801d8ba12ac032f40a12a55e72f79d52c9bb" +checksum = "8abfca0960131262254a91d02ff4903526a261ede730d7a2c75b4234c867cdc0" dependencies = [ "annotate-snippets", "atty", @@ -2959,41 +3235,41 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_index" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea" +checksum = "5a395509dcb90a92c1479c085639594624e06b4ab3fc7c1b795b46a61f2d4f65" dependencies = [ "rustc-ap-serialize", - "smallvec", + "smallvec 0.6.10", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0c064676f8a08e42a36b0d4e4a102465fb0f4b75e11436cb7f66d2c3fa7139" +checksum = "64eac8a0e6efb8f55292aa24be0208c7c0538236c613e79952fd1fa3d54bcf8e" dependencies = [ "unicode-xid 0.2.0", ] [[package]] name = "rustc-ap-rustc_macros" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2d77e46159c5288c585decbcdc9d742889c65e307c31e104c7a36d63fe1f5d0" +checksum = "f99795e8be4877e9e05d59f201e1740c1cf673364655def5848606d9e25b75af" dependencies = [ "itertools 0.8.0", - "proc-macro2 0.4.30", - "quote 0.6.12", - "syn 0.15.35", - "synstructure 0.10.2", + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.11", + "synstructure 0.12.1", ] [[package]] name = "rustc-ap-rustc_target" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ca895350b0de14d064b499168c93fa183958d5462eb042c927d93623e41ec1" +checksum = "f22e21fdd8e1c0030f507158fa79b9f1e080e6241aba994d0f97c14a0a07a826" dependencies = [ "bitflags", "log", @@ -3005,19 +3281,19 @@ dependencies = [ [[package]] name = "rustc-ap-serialize" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20" +checksum = "bb1cd6ef5135408d62559866e79986ca261f4c1333253d500e5e66fe66d1432e" dependencies = [ "indexmap", - "smallvec", + "smallvec 0.6.10", ] [[package]] name = "rustc-ap-syntax" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0c30f8e38c847dbfd9e2f1e472ab06d0bd0a23ab53ae4c5a44912842ce834e" +checksum = "61fc1c901d2cbd24cae95d7bc5a58aa7661ec3dc5320c78c32830a52a685c33c" dependencies = [ "bitflags", "lazy_static 1.3.0", @@ -3030,14 +3306,14 @@ dependencies = [ "rustc-ap-serialize", "rustc-ap-syntax_pos", "scoped-tls", - "smallvec", + "smallvec 0.6.10", ] [[package]] name = "rustc-ap-syntax_pos" -version = "606.0.0" +version = "610.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdaa0fb40143b4b878256ac4e2b498885daafc269502504d91929eab4744bf4" +checksum = "230534f638255853bb9f13987537e00a818435a0cc54b68d97221b6822c8f1bc" dependencies = [ "cfg-if", "rustc-ap-arena", @@ -3078,17 +3354,6 @@ dependencies = [ "rustc_target", ] -[[package]] -name = "rustc-rayon" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" -dependencies = [ - "crossbeam-deque 0.2.0", - "either", - "rustc-rayon-core 0.2.0", -] - [[package]] name = "rustc-rayon" version = "0.3.0" @@ -3097,19 +3362,7 @@ checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" dependencies = [ "crossbeam-deque 0.7.1", "either", - "rustc-rayon-core 0.3.0", -] - -[[package]] -name = "rustc-rayon-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" -dependencies = [ - "crossbeam-deque 0.2.0", - "lazy_static 1.3.0", - "libc", - "num_cpus", + "rustc-rayon-core", ] [[package]] @@ -3153,10 +3406,10 @@ dependencies = [ "crossbeam-utils 0.6.5", "serde", "serde_json", - "smallvec", + "smallvec 0.6.10", "syn 0.15.35", "url 2.1.0", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -3164,7 +3417,7 @@ name = "rustc_apfloat" version = "0.0.0" dependencies = [ "bitflags", - "smallvec", + "smallvec 1.0.0", ] [[package]] @@ -3182,7 +3435,27 @@ dependencies = [ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ + "bitflags", + "flate2", + "libc", + "log", + "rustc", + "rustc-demangle", + "rustc_codegen_ssa", + "rustc_codegen_utils", + "rustc_data_structures", + "rustc_errors", + "rustc_feature", + "rustc_fs_util", + "rustc_incremental", + "rustc_index", "rustc_llvm", + "rustc_session", + "rustc_target", + "smallvec 0.6.10", + "syntax", + "syntax_expand", + "syntax_pos", ] [[package]] @@ -3200,10 +3473,12 @@ dependencies = [ "rustc_apfloat", "rustc_codegen_utils", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", "rustc_fs_util", "rustc_incremental", "rustc_index", + "rustc_session", "rustc_target", "serialize", "syntax", @@ -3230,6 +3505,7 @@ dependencies = [ name = "rustc_data_structures" version = "0.0.0" dependencies = [ + "bitflags", "cfg-if", "crossbeam-utils 0.6.5", "ena", @@ -3238,13 +3514,14 @@ dependencies = [ "jobserver", "lazy_static 1.3.0", "log", + "measureme", "parking_lot 0.9.0", "rustc-hash", - "rustc-rayon 0.3.0", - "rustc-rayon-core 0.3.0", + "rustc-rayon", + "rustc-rayon-core", "rustc_index", "serialize", - "smallvec", + "smallvec 1.0.0", "stable_deref_trait", ] @@ -3259,13 +3536,16 @@ dependencies = [ "rustc", "rustc_codegen_utils", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", + "rustc_feature", "rustc_interface", "rustc_lint", "rustc_metadata", "rustc_mir", - "rustc_plugin", + "rustc_parse", "rustc_plugin_impl", + "rustc_resolve", "rustc_save_analysis", "rustc_target", "serialize", @@ -3273,6 +3553,10 @@ dependencies = [ "syntax_pos", ] +[[package]] +name = "rustc_error_codes" +version = "0.0.0" + [[package]] name = "rustc_errors" version = "0.0.0" @@ -3288,6 +3572,15 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "rustc_feature" +version = "0.0.0" +dependencies = [ + "lazy_static 1.3.0", + "rustc_data_structures", + "syntax_pos", +] + [[package]] name = "rustc_fs_util" version = "0.0.0" @@ -3302,6 +3595,7 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_fs_util", + "rustc_session", "serialize", "syntax", "syntax_pos", @@ -3312,7 +3606,7 @@ name = "rustc_index" version = "0.0.0" dependencies = [ "serialize", - "smallvec", + "smallvec 1.0.0", ] [[package]] @@ -3322,7 +3616,8 @@ dependencies = [ "log", "once_cell", "rustc", - "rustc-rayon 0.3.0", + "rustc-rayon", + "rustc_codegen_llvm", "rustc_codegen_ssa", "rustc_codegen_utils", "rustc_data_structures", @@ -3331,6 +3626,7 @@ dependencies = [ "rustc_lint", "rustc_metadata", "rustc_mir", + "rustc_parse", "rustc_passes", "rustc_plugin_impl", "rustc_privacy", @@ -3339,7 +3635,7 @@ dependencies = [ "rustc_traits", "rustc_typeck", "serialize", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_expand", "syntax_ext", @@ -3361,7 +3657,10 @@ dependencies = [ "log", "rustc", "rustc_data_structures", + "rustc_error_codes", + "rustc_feature", "rustc_index", + "rustc_session", "rustc_target", "syntax", "syntax_pos", @@ -3373,6 +3672,7 @@ version = "0.0.0" dependencies = [ "build_helper", "cc", + "libc", ] [[package]] @@ -3393,7 +3693,7 @@ dependencies = [ "itertools 0.8.0", "proc-macro2 1.0.3", "quote 1.0.2", - "syn 1.0.5", + "syn 1.0.11", "synstructure 0.12.1", ] @@ -3406,11 +3706,13 @@ dependencies = [ "memmap", "rustc", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", "rustc_index", + "rustc_parse", "rustc_target", "serialize", - "smallvec", + "smallvec 1.0.0", "stable_deref_trait", "syntax", "syntax_expand", @@ -3424,18 +3726,21 @@ dependencies = [ "arena", "either", "graphviz", + "itertools 0.8.0", "log", "log_settings", "polonius-engine", "rustc", "rustc_apfloat", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", "rustc_index", "rustc_lexer", + "rustc_macros", "rustc_target", "serialize", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_pos", ] @@ -3452,24 +3757,36 @@ dependencies = [ ] [[package]] -name = "rustc_passes" +name = "rustc_parse" version = "0.0.0" dependencies = [ + "bitflags", "log", - "rustc", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", - "rustc_index", - "rustc_target", + "rustc_feature", + "rustc_lexer", + "smallvec 1.0.0", "syntax", "syntax_pos", ] [[package]] -name = "rustc_plugin" +name = "rustc_passes" version = "0.0.0" dependencies = [ - "rustc_plugin_impl", + "log", + "rustc", + "rustc_data_structures", + "rustc_error_codes", + "rustc_errors", + "rustc_feature", + "rustc_index", + "rustc_parse", + "rustc_target", + "syntax", + "syntax_pos", ] [[package]] @@ -3477,9 +3794,9 @@ name = "rustc_plugin_impl" version = "0.0.0" dependencies = [ "rustc", + "rustc_error_codes", "rustc_metadata", "syntax", - "syntax_expand", "syntax_pos", ] @@ -3490,6 +3807,7 @@ dependencies = [ "log", "rustc", "rustc_data_structures", + "rustc_error_codes", "rustc_typeck", "syntax", "syntax_pos", @@ -3504,9 +3822,11 @@ dependencies = [ "log", "rustc", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", + "rustc_feature", "rustc_metadata", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_expand", "syntax_pos", @@ -3522,12 +3842,28 @@ dependencies = [ "rustc", "rustc_codegen_utils", "rustc_data_structures", - "rustc_target", + "rustc_parse", "serde_json", "syntax", "syntax_pos", ] +[[package]] +name = "rustc_session" +version = "0.0.0" +dependencies = [ + "log", + "num_cpus", + "rustc_data_structures", + "rustc_errors", + "rustc_feature", + "rustc_fs_util", + "rustc_index", + "rustc_target", + "serialize", + "syntax_pos", +] + [[package]] name = "rustc_target" version = "0.0.0" @@ -3536,6 +3872,7 @@ dependencies = [ "log", "rustc_data_structures", "rustc_index", + "rustc_macros", "serialize", "syntax_pos", ] @@ -3558,8 +3895,9 @@ dependencies = [ "log", "rustc", "rustc_data_structures", + "rustc_macros", "rustc_target", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_pos", ] @@ -3583,10 +3921,11 @@ dependencies = [ "log", "rustc", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", "rustc_index", "rustc_target", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_pos", ] @@ -3606,7 +3945,9 @@ version = "0.0.0" dependencies = [ "minifier", "pulldown-cmark 0.5.3", - "rustc-rayon 0.3.0", + "rustc-rayon", + "serde", + "serde_json", "tempfile", ] @@ -3640,12 +3981,12 @@ dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", "serde", - "syn 1.0.5", + "syn 1.0.11", ] [[package]] name = "rustfmt-nightly" -version = "1.4.9" +version = "1.4.11" dependencies = [ "annotate-snippets", "bytecount", @@ -3698,7 +4039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" dependencies = [ "lazy_static 1.3.0", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -3725,6 +4066,27 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +[[package]] +name = "security-framework" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" +dependencies = [ + "core-foundation 0.6.3", + "core-foundation-sys 0.6.2", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" +dependencies = [ + "core-foundation-sys 0.6.2", +] + [[package]] name = "semver" version = "0.9.0" @@ -3789,7 +4151,19 @@ checksum = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", - "syn 1.0.5", + "syn 1.0.11", +] + +[[package]] +name = "serde_urlencoded" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +dependencies = [ + "dtoa", + "itoa", + "serde", + "url 1.7.2", ] [[package]] @@ -3797,7 +4171,7 @@ name = "serialize" version = "0.0.0" dependencies = [ "indexmap", - "smallvec", + "smallvec 1.0.0", ] [[package]] @@ -3842,10 +4216,11 @@ checksum = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" [[package]] name = "sized-chunks" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a2eb3fe454976eefb479f78f9b394d34d661b647c6326a3a6e66f68bb12c26" +checksum = "62db64dd92b3b54314b1e216c274634ca2b3fe8da8b3873be670cb1ac4dad30f" dependencies = [ + "bitmaps", "typenum", ] @@ -3861,6 +4236,12 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +[[package]] +name = "smallvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" + [[package]] name = "socket2" version = "0.3.8" @@ -3870,7 +4251,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -3902,7 +4283,16 @@ dependencies = [ "rustc_msan", "rustc_tsan", "unwind", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +dependencies = [ + "bytes", ] [[package]] @@ -3974,7 +4364,7 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.3", "quote 1.0.2", - "syn 1.0.5", + "syn 1.0.11", ] [[package]] @@ -4008,9 +4398,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.5" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +checksum = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", @@ -4037,7 +4427,7 @@ checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", - "syn 1.0.5", + "syn 1.0.11", "unicode-xid 0.2.0", ] @@ -4049,13 +4439,16 @@ dependencies = [ "lazy_static 1.3.0", "log", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", + "rustc_feature", "rustc_index", "rustc_lexer", - "rustc_target", + "rustc_macros", + "rustc_session", "scoped-tls", "serialize", - "smallvec", + "smallvec 1.0.0", "syntax_pos", ] @@ -4063,17 +4456,14 @@ dependencies = [ name = "syntax_expand" version = "0.0.0" dependencies = [ - "bitflags", - "lazy_static 1.3.0", "log", "rustc_data_structures", "rustc_errors", - "rustc_index", + "rustc_feature", "rustc_lexer", - "rustc_target", - "scoped-tls", + "rustc_parse", "serialize", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_pos", ] @@ -4085,9 +4475,12 @@ dependencies = [ "fmt_macros", "log", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", + "rustc_feature", + "rustc_parse", "rustc_target", - "smallvec", + "smallvec 1.0.0", "syntax", "syntax_expand", "syntax_pos", @@ -4099,6 +4492,7 @@ version = "0.0.0" dependencies = [ "arena", "cfg-if", + "log", "rustc_data_structures", "rustc_index", "rustc_macros", @@ -4130,7 +4524,7 @@ dependencies = [ "rand 0.7.0", "redox_syscall", "remove_dir_all", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -4160,7 +4554,7 @@ checksum = "0dd90505d5006a4422d3520b30c781d480b3f36768c2fa2187c3e950bc110464" dependencies = [ "byteorder", "dirs", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -4208,6 +4602,17 @@ dependencies = [ "term 0.0.0", ] +[[package]] +name = "tester" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee72ec31009a42b53de9a6b7d8f462b493ab3b1e4767bda1fcdbb52127f13b6c" +dependencies = [ + "getopts", + "libc", + "term 0.6.0", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -4239,13 +4644,13 @@ dependencies = [ [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" dependencies = [ "libc", "redox_syscall", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -4271,6 +4676,17 @@ dependencies = [ "tokio-uds", ] +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +dependencies = [ + "bytes", + "either", + "futures", +] + [[package]] name = "tokio-codec" version = "0.1.1" @@ -4350,7 +4766,7 @@ dependencies = [ "tokio-io", "tokio-reactor", "tokio-signal", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -4394,7 +4810,7 @@ dependencies = [ "tokio-executor", "tokio-io", "tokio-reactor", - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -4507,6 +4923,21 @@ dependencies = [ "syn 0.15.35", ] +[[package]] +name = "try-lock" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" + +[[package]] +name = "try_from" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" +dependencies = [ + "cfg-if", +] + [[package]] name = "typenum" version = "1.10.0" @@ -4531,7 +4962,7 @@ version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" dependencies = [ - "version_check", + "version_check 0.1.5", ] [[package]] @@ -4551,9 +4982,9 @@ checksum = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" [[package]] name = "unicode-segmentation" -version = "1.2.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" @@ -4622,7 +5053,7 @@ checksum = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" dependencies = [ "idna 0.2.0", "matches", - "percent-encoding 2.0.0", + "percent-encoding 2.1.0", "serde", ] @@ -4644,6 +5075,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" +[[package]] +name = "uuid" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" +dependencies = [ + "rand 0.6.1", +] + [[package]] name = "vcpkg" version = "0.2.6" @@ -4673,6 +5113,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" + [[package]] name = "vte" version = "0.3.3" @@ -4689,15 +5135,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" dependencies = [ "same-file", - "winapi 0.3.6", + "winapi 0.3.8", "winapi-util", ] +[[package]] +name = "want" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +dependencies = [ + "futures", + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -4712,9 +5175,9 @@ checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", @@ -4738,7 +5201,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" dependencies = [ - "winapi 0.3.6", + "winapi 0.3.8", ] [[package]] @@ -4753,10 +5216,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" dependencies = [ - "winapi 0.3.6", + "winapi 0.3.8", "winapi-util", ] +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi 0.3.8", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/README.md b/README.md index c5468a2924..61d3c9e115 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The Rust build system has a Python script called `x.py` to bootstrap building the compiler. More information about it may be found by running `./x.py --help` or reading the [rustc guide][rustcguidebuild]. -[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html +[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/building/how-to-build-and-run.html ### Building on *nix 1. Make sure you have installed the dependencies: diff --git a/RELEASES.md b/RELEASES.md index 6daf7a13b6..3e06f23c59 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,265 @@ +Version 1.41.1 (2020-02-27) +=========================== + +* [Always check types of static items][69145] +* [Always check lifetime bounds of `Copy` impls][69145] +* [Fix miscompilation in callers of `Layout::repeat`][69225] + +[69225]: https://github.com/rust-lang/rust/issues/69225 +[69145]: https://github.com/rust-lang/rust/pull/69145 + +Version 1.41.0 (2020-01-30) +=========================== + +Language +-------- + +- [You can now pass type parameters to foreign items when implementing + traits.][65879] E.g. You can now write `impl From for Vec {}`. +- [You can now arbitrarily nest receiver types in the `self` position.][64325] E.g. you can + now write `fn foo(self: Box>) {}`. Previously only `Self`, `&Self`, + `&mut Self`, `Arc`, `Rc`, and `Box` were allowed. +- [You can now use any valid identifier in a `format_args` macro.][66847] + Previously identifiers starting with an underscore were not allowed. +- [Visibility modifiers (e.g. `pub`) are now syntactically allowed on trait items and + enum variants.][66183] These are still rejected semantically, but + can be seen and parsed by procedural macros and conditional compilation. + +Compiler +-------- + +- [Rustc will now warn if you have unused loop `'label`s.][66325] +- [Removed support for the `i686-unknown-dragonfly` target.][67255] +- [Added tier 3 support\* for the `riscv64gc-unknown-linux-gnu` target.][66661] +- [You can now pass an arguments file passing the `@path` syntax + to rustc.][66172] Note that the format differs somewhat from what is + found in other tooling; please see [the documentation][argfile-docs] for + more information. +- [You can now provide `--extern` flag without a path, indicating that it is + available from the search path or specified with an `-L` flag.][64882] + +\* Refer to Rust's [platform support page][forge-platform-support] for more +information on Rust's tiered platform support. + +[argfile-docs]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#path-load-command-line-flags-from-a-path + +Libraries +--------- + +- [The `core::panic` module is now stable.][66771] It was already stable + through `std`. +- [`NonZero*` numerics now implement `From` if it's a smaller integer + width.][66277] E.g. `NonZeroU16` now implements `From`. +- [`MaybeUninit` now implements `fmt::Debug`.][65013] + +Stabilized APIs +--------------- + +- [`Result::map_or`] +- [`Result::map_or_else`] +- [`std::rc::Weak::weak_count`] +- [`std::rc::Weak::strong_count`] +- [`std::sync::Weak::weak_count`] +- [`std::sync::Weak::strong_count`] + +Cargo +----- + +- [Cargo will now document all the private items for binary crates + by default.][cargo/7593] +- [`cargo-install` will now reinstall the package if it detects that it is out + of date.][cargo/7560] +- [Cargo.lock now uses a more git friendly format that should help to reduce + merge conflicts.][cargo/7579] +- [You can now override specific dependencies's build settings][cargo/7591] E.g. + `[profile.dev.package.image] opt-level = 2` sets the `image` crate's + optimisation level to `2` for debug builds. You can also use + `[profile..build-override]` to override build scripts and + their dependencies. + +Misc +---- + +- [You can now specify `edition` in documentation code blocks to compile the block + for that edition.][66238] E.g. `edition2018` tells rustdoc that the code sample + should be compiled the 2018 edition of Rust. +- [You can now provide custom themes to rustdoc with `--theme`, and check the + current theme with `--check-theme`.][54733] +- [You can use `#[cfg(doc)]` to compile an item when building documentation.][61351] + +Compatibility Notes +------------------- + +- [As previously announced 1.41.0 will be the last tier 1 release for 32-bit + Apple targets.][apple-32bit-drop] This means that the source code is still + available to build, but the targets are no longer being tested and release + binaries for those platforms will no longer be distributed by the Rust project. + Please refer to the linked blog post for more information. + +[54733]: https://github.com/rust-lang/rust/pull/54733/ +[61351]: https://github.com/rust-lang/rust/pull/61351/ +[67255]: https://github.com/rust-lang/rust/pull/67255/ +[66661]: https://github.com/rust-lang/rust/pull/66661/ +[66771]: https://github.com/rust-lang/rust/pull/66771/ +[66847]: https://github.com/rust-lang/rust/pull/66847/ +[66238]: https://github.com/rust-lang/rust/pull/66238/ +[66277]: https://github.com/rust-lang/rust/pull/66277/ +[66325]: https://github.com/rust-lang/rust/pull/66325/ +[66172]: https://github.com/rust-lang/rust/pull/66172/ +[66183]: https://github.com/rust-lang/rust/pull/66183/ +[65879]: https://github.com/rust-lang/rust/pull/65879/ +[65013]: https://github.com/rust-lang/rust/pull/65013/ +[64882]: https://github.com/rust-lang/rust/pull/64882/ +[64325]: https://github.com/rust-lang/rust/pull/64325/ +[cargo/7560]: https://github.com/rust-lang/cargo/pull/7560/ +[cargo/7579]: https://github.com/rust-lang/cargo/pull/7579/ +[cargo/7591]: https://github.com/rust-lang/cargo/pull/7591/ +[cargo/7593]: https://github.com/rust-lang/cargo/pull/7593/ +[`Result::map_or_else`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else +[`Result::map_or`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or +[`std::rc::Weak::weak_count`]: https://doc.rust-lang.org/std/rc/struct.Weak.html#method.weak_count +[`std::rc::Weak::strong_count`]: https://doc.rust-lang.org/std/rc/struct.Weak.html#method.strong_count +[`std::sync::Weak::weak_count`]: https://doc.rust-lang.org/std/sync/struct.Weak.html#method.weak_count +[`std::sync::Weak::strong_count`]: https://doc.rust-lang.org/std/sync/struct.Weak.html#method.strong_count +[apple-32bit-drop]: https://blog.rust-lang.org/2020/01/03/reducing-support-for-32-bit-apple-targets.html + +Version 1.40.0 (2019-12-19) +=========================== + +Language +-------- +- [You can now use tuple `struct`s and tuple `enum` variant's constructors in + `const` contexts.][65188] e.g. + + ```rust + pub struct Point(i32, i32); + + const ORIGIN: Point = { + let constructor = Point; + + constructor(0, 0) + }; + ``` + +- [You can now mark `struct`s, `enum`s, and `enum` variants with the `#[non_exhaustive]` attribute to + indicate that there may be variants or fields added in the future.][64639] + For example this requires adding a wild-card branch (`_ => {}`) to any match + statements on a non-exhaustive `enum`. [(RFC 2008)] +- [You can now use function-like procedural macros in `extern` blocks and in + type positions.][63931] e.g. `type Generated = macro!();` +- [Function-like and attribute procedural macros can now emit + `macro_rules!` items, so you can now have your macros generate macros.][64035] +- [The `meta` pattern matcher in `macro_rules!` now correctly matches the modern + attribute syntax.][63674] For example `(#[$m:meta])` now matches `#[attr]`, + `#[attr{tokens}]`, `#[attr[tokens]]`, and `#[attr(tokens)]`. + +Compiler +-------- +- [Added tier 3 support\* for the + `thumbv7neon-unknown-linux-musleabihf` target.][66103] +- [Added tier 3 support for the + `aarch64-unknown-none-softfloat` target.][64589] +- [Added tier 3 support for the `mips64-unknown-linux-muslabi64`, and + `mips64el-unknown-linux-muslabi64` targets.][65843] + +\* Refer to Rust's [platform support page][forge-platform-support] for more + information on Rust's tiered platform support. + +Libraries +--------- +- [The `is_power_of_two` method on unsigned numeric types is now a `const` function.][65092] + +Stabilized APIs +--------------- +- [`BTreeMap::get_key_value`] +- [`HashMap::get_key_value`] +- [`Option::as_deref_mut`] +- [`Option::as_deref`] +- [`Option::flatten`] +- [`UdpSocket::peer_addr`] +- [`f32::to_be_bytes`] +- [`f32::to_le_bytes`] +- [`f32::to_ne_bytes`] +- [`f64::to_be_bytes`] +- [`f64::to_le_bytes`] +- [`f64::to_ne_bytes`] +- [`f32::from_be_bytes`] +- [`f32::from_le_bytes`] +- [`f32::from_ne_bytes`] +- [`f64::from_be_bytes`] +- [`f64::from_le_bytes`] +- [`f64::from_ne_bytes`] +- [`mem::take`] +- [`slice::repeat`] +- [`todo!`] + +Cargo +----- +- [Cargo will now always display warnings, rather than only on + fresh builds.][cargo/7450] +- [Feature flags (except `--all-features`) passed to a virtual workspace will + now produce an error.][cargo/7507] Previously these flags were ignored. +- [You can now publish `dev-dependencies` without including + a `version`.][cargo/7333] + +Misc +---- +- [You can now specify the `#[cfg(doctest)]` attribute to include an item only + when running documentation tests with `rustdoc`.][63803] + +Compatibility Notes +------------------- +- [As previously announced, any previous NLL warnings in the 2015 edition are + now hard errors.][64221] +- [The `include!` macro will now warn if it failed to include the + entire file.][64284] The `include!` macro unintentionally only includes the + first _expression_ in a file, and this can be unintuitive. This will become + either a hard error in a future release, or the behavior may be fixed to include all expressions as expected. +- [Using `#[inline]` on function prototypes and consts now emits a warning under + `unused_attribute` lint.][65294] Using `#[inline]` anywhere else inside traits + or `extern` blocks now correctly emits a hard error. + +[65294]: https://github.com/rust-lang/rust/pull/65294/ +[66103]: https://github.com/rust-lang/rust/pull/66103/ +[65843]: https://github.com/rust-lang/rust/pull/65843/ +[65188]: https://github.com/rust-lang/rust/pull/65188/ +[65092]: https://github.com/rust-lang/rust/pull/65092/ +[64589]: https://github.com/rust-lang/rust/pull/64589/ +[64639]: https://github.com/rust-lang/rust/pull/64639/ +[64221]: https://github.com/rust-lang/rust/pull/64221/ +[64284]: https://github.com/rust-lang/rust/pull/64284/ +[63931]: https://github.com/rust-lang/rust/pull/63931/ +[64035]: https://github.com/rust-lang/rust/pull/64035/ +[63674]: https://github.com/rust-lang/rust/pull/63674/ +[63803]: https://github.com/rust-lang/rust/pull/63803/ +[cargo/7450]: https://github.com/rust-lang/cargo/pull/7450/ +[cargo/7507]: https://github.com/rust-lang/cargo/pull/7507/ +[cargo/7525]: https://github.com/rust-lang/cargo/pull/7525/ +[cargo/7333]: https://github.com/rust-lang/cargo/pull/7333/ +[(rfc 2008)]: https://rust-lang.github.io/rfcs/2008-non-exhaustive.html +[`f32::to_be_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_be_bytes +[`f32::to_le_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_le_bytes +[`f32::to_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_ne_bytes +[`f64::to_be_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_be_bytes +[`f64::to_le_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_le_bytes +[`f64::to_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_ne_bytes +[`f32::from_be_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_be_bytes +[`f32::from_le_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_le_bytes +[`f32::from_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.from_ne_bytes +[`f64::from_be_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_be_bytes +[`f64::from_le_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_le_bytes +[`f64::from_ne_bytes`]: https://doc.rust-lang.org/std/primitive.f64.html#method.from_ne_bytes +[`option::flatten`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.flatten +[`option::as_deref`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_deref +[`option::as_deref_mut`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_deref_mut +[`hashmap::get_key_value`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get_key_value +[`btreemap::get_key_value`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.get_key_value +[`slice::repeat`]: https://doc.rust-lang.org/std/primitive.slice.html#method.repeat +[`mem::take`]: https://doc.rust-lang.org/std/mem/fn.take.html +[`udpsocket::peer_addr`]: https://doc.rust-lang.org/std/net/struct.UdpSocket.html#method.peer_addr +[`todo!`]: https://doc.rust-lang.org/std/macro.todo.html + + Version 1.39.0 (2019-11-07) =========================== @@ -7804,7 +8066,7 @@ Version 0.7 (2013-07-03) * extra: Implementation of fixed output size variations of SHA-2. * Tooling - * `unused_variable` lint mode for unused variables (default: warn). + * `unused_variables` lint mode for unused variables (default: warn). * `unused_unsafe` lint mode for detecting unnecessary `unsafe` blocks (default: warn). * `unused_mut` lint mode for identifying unused `mut` qualifiers diff --git a/config.toml.example b/config.toml.example index e832570ed9..5152a6c988 100644 --- a/config.toml.example +++ b/config.toml.example @@ -379,9 +379,6 @@ # and currently the only standard option supported is `"llvm"` #codegen-backends = ["llvm"] -# This is the name of the directory in which codegen backends will get installed -#codegen-backends-dir = "codegen-backends" - # Indicates whether LLD will be compiled and made available in the sysroot for # rustc to execute. #lld = false diff --git a/git-commit-hash b/git-commit-hash index 70479621bc..0e1e3ce434 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -73528e339aae0f17a15ffa49a8ac608f50c6cf14 \ No newline at end of file +f3e1a954d2ead4e2fc197c7da7d71e6c61bad196 \ No newline at end of file diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index a13ff69a7b..6937fb922d 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -25,7 +25,7 @@ fn main() { let mut dylib_path = bootstrap::util::dylib_path(); dylib_path.insert(0, PathBuf::from(libdir.clone())); - //FIXME(misdreavus): once stdsimd uses cfg(rustdoc) instead of cfg(dox), remove the `--cfg dox` + //FIXME(misdreavus): once stdsimd uses cfg(doc) instead of cfg(dox), remove the `--cfg dox` //arguments here let mut cmd = Command::new(rustdoc); cmd.args(&args) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4caf36a6f2..bb16941488 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -102,10 +102,10 @@ def verify(path, sha_path, verbose): return verified -def unpack(tarball, dst, verbose=False, match=None): +def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): """Unpack the given tarball file""" print("extracting", tarball) - fname = os.path.basename(tarball).replace(".tar.gz", "") + fname = os.path.basename(tarball).replace(tarball_suffix, "") with contextlib.closing(tarfile.open(tarball)) as tar: for member in tar.getnames(): if "/" not in member: @@ -331,6 +331,7 @@ class RustBuild(object): self.use_vendored_sources = '' self.verbose = False + def download_stage0(self): """Fetch the build system for Rust, written in Rust @@ -344,18 +345,30 @@ class RustBuild(object): rustc_channel = self.rustc_channel cargo_channel = self.cargo_channel + def support_xz(): + try: + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + temp_path = temp_file.name + with tarfile.open(temp_path, "w:xz") as tar: + pass + return True + except tarfile.CompressionError: + return False + if self.rustc().startswith(self.bin_root()) and \ (not os.path.exists(self.rustc()) or self.program_out_of_date(self.rustc_stamp())): if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) - filename = "rust-std-{}-{}.tar.gz".format( - rustc_channel, self.build) + tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' + filename = "rust-std-{}-{}{}".format( + rustc_channel, self.build, tarball_suffix) pattern = "rust-std-{}".format(self.build) - self._download_stage0_helper(filename, pattern) + self._download_stage0_helper(filename, pattern, tarball_suffix) - filename = "rustc-{}-{}.tar.gz".format(rustc_channel, self.build) - self._download_stage0_helper(filename, "rustc") + filename = "rustc-{}-{}{}".format(rustc_channel, self.build, + tarball_suffix) + self._download_stage0_helper(filename, "rustc", tarball_suffix) self.fix_executable("{}/bin/rustc".format(self.bin_root())) self.fix_executable("{}/bin/rustdoc".format(self.bin_root())) with output(self.rustc_stamp()) as rust_stamp: @@ -365,20 +378,22 @@ class RustBuild(object): # libraries/binaries that are included in rust-std with # the system MinGW ones. if "pc-windows-gnu" in self.build: - filename = "rust-mingw-{}-{}.tar.gz".format( - rustc_channel, self.build) - self._download_stage0_helper(filename, "rust-mingw") + filename = "rust-mingw-{}-{}{}".format( + rustc_channel, self.build, tarball_suffix) + self._download_stage0_helper(filename, "rust-mingw", tarball_suffix) if self.cargo().startswith(self.bin_root()) and \ (not os.path.exists(self.cargo()) or self.program_out_of_date(self.cargo_stamp())): - filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build) - self._download_stage0_helper(filename, "cargo") + tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' + filename = "cargo-{}-{}{}".format(cargo_channel, self.build, + tarball_suffix) + self._download_stage0_helper(filename, "cargo", tarball_suffix) self.fix_executable("{}/bin/cargo".format(self.bin_root())) with output(self.cargo_stamp()) as cargo_stamp: cargo_stamp.write(self.date) - def _download_stage0_helper(self, filename, pattern): + def _download_stage0_helper(self, filename, pattern, tarball_suffix): cache_dst = os.path.join(self.build_dir, "cache") rustc_cache = os.path.join(cache_dst, self.date) if not os.path.exists(rustc_cache): @@ -388,7 +403,7 @@ class RustBuild(object): tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) - unpack(tarball, self.bin_root(), match=pattern, verbose=self.verbose) + unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose) @staticmethod def fix_executable(fname): @@ -628,7 +643,9 @@ class RustBuild(object): env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ (os.pathsep + env["LIBRARY_PATH"]) \ if "LIBRARY_PATH" in env else "" - env["RUSTFLAGS"] = "-Cdebuginfo=2 " + # preserve existing RUSTFLAGS + env.setdefault("RUSTFLAGS", "") + env["RUSTFLAGS"] += " -Cdebuginfo=2" build_section = "target.{}".format(self.build_triple()) target_features = [] @@ -637,13 +654,13 @@ class RustBuild(object): elif self.get_toml("crt-static", build_section) == "false": target_features += ["-crt-static"] if target_features: - env["RUSTFLAGS"] += "-C target-feature=" + (",".join(target_features)) + " " + env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features)) target_linker = self.get_toml("linker", build_section) if target_linker is not None: - env["RUSTFLAGS"] += "-C linker=" + target_linker + " " - env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes " + env["RUSTFLAGS"] += " -C linker=" + target_linker + env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" if self.get_toml("deny-warnings", "rust") != "false": - env["RUSTFLAGS"] += "-Dwarnings " + env["RUSTFLAGS"] += " -Dwarnings" env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 2edcef203a..8b0ad169cf 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -339,7 +339,6 @@ impl<'a> Builder<'a> { Kind::Build => describe!( compile::Std, compile::Rustc, - compile::CodegenBackend, compile::StartupObjects, tool::BuildManifest, tool::Rustbook, @@ -364,10 +363,10 @@ impl<'a> Builder<'a> { Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, check::Rustc, - check::CodegenBackend, check::Rustdoc ), Kind::Test => describe!( + crate::toolstate::ToolStateCheck, test::Tidy, test::Ui, test::CompileFail, @@ -631,11 +630,6 @@ impl<'a> Builder<'a> { self.ensure(Libdir { compiler, target }) } - pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf { - self.sysroot_libdir(compiler, compiler.host) - .with_file_name(self.config.rust_codegen_backends_dir.clone()) - } - /// Returns the compiler's libdir where it stores the dynamic libraries that /// it itself links against. /// @@ -706,15 +700,6 @@ impl<'a> Builder<'a> { } } - /// Gets the paths to all of the compiler's codegen backends. - fn codegen_backends(&self, compiler: Compiler) -> impl Iterator { - fs::read_dir(self.sysroot_codegen_backends(compiler)) - .into_iter() - .flatten() - .filter_map(Result::ok) - .map(|entry| entry.path()) - } - pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { self.ensure(tool::Rustdoc { compiler }) } @@ -758,12 +743,6 @@ impl<'a> Builder<'a> { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); - // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, - // so we need to explicitly clear out if they've been updated. - for backend in self.codegen_backends(compiler) { - self.clear_if_dirty(&out_dir, &backend); - } - if cmd == "doc" || cmd == "rustdoc" { let my_out = match mode { // This is the intended out directory for compiler documentation. @@ -980,7 +959,7 @@ impl<'a> Builder<'a> { // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it // fun to pass a flag to a tool to pass a flag to pass a flag to a tool // to change a flag in a binary? - if self.config.rust_rpath { + if self.config.rust_rpath && util::use_host_linker(&target) { let rpath = if target.contains("apple") { // Note that we need to take one extra step on macOS to also pass @@ -990,10 +969,7 @@ impl<'a> Builder<'a> { // flesh out rpath support more fully in the future. rustflags.arg("-Zosx-rpath-install-name"); Some("-Wl,-rpath,@loader_path/../lib") - } else if !target.contains("windows") && - !target.contains("wasm32") && - !target.contains("emscripten") && - !target.contains("fuchsia") { + } else if !target.contains("windows") { Some("-Wl,-rpath,$ORIGIN/../lib") } else { None @@ -1242,7 +1218,8 @@ impl<'a> Builder<'a> { cargo.arg("--frozen"); } - cargo.env("RUSTC_INSTALL_BINDIR", &self.config.bindir); + // Try to use a sysroot-relative bindir, in case it was configured absolutely. + cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative()); self.ci_env.force_coloring_in_ci(&mut cargo); diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index 2bb90fdb04..b9d97fb8b7 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -363,6 +363,10 @@ fn dist_with_same_targets_and_hosts() { compiler: Compiler { host: a, stage: 1 }, target: b, }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, ] ); assert_eq!( diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index ef1b6e217a..d265b6eb2d 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.40.0"; +pub const CFG_RELEASE_NUM: &str = "1.41.1"; pub struct GitInfo { inner: Option, @@ -29,31 +29,28 @@ impl GitInfo { pub fn new(ignore_git: bool, dir: &Path) -> GitInfo { // See if this even begins to look like a git dir if ignore_git || !dir.join(".git").exists() { - return GitInfo { inner: None } + return GitInfo { inner: None }; } // Make sure git commands work - match Command::new("git") - .arg("rev-parse") - .current_dir(dir) - .output() - { + match Command::new("git").arg("rev-parse").current_dir(dir).output() { Ok(ref out) if out.status.success() => {} _ => return GitInfo { inner: None }, } // Ok, let's scrape some info - let ver_date = output(Command::new("git").current_dir(dir) - .arg("log").arg("-1") - .arg("--date=short") - .arg("--pretty=format:%cd")); - let ver_hash = output(Command::new("git").current_dir(dir) - .arg("rev-parse").arg("HEAD")); - let short_ver_hash = output(Command::new("git") - .current_dir(dir) - .arg("rev-parse") - .arg("--short=9") - .arg("HEAD")); + let ver_date = output( + Command::new("git") + .current_dir(dir) + .arg("log") + .arg("-1") + .arg("--date=short") + .arg("--pretty=format:%cd"), + ); + let ver_hash = output(Command::new("git").current_dir(dir).arg("rev-parse").arg("HEAD")); + let short_ver_hash = output( + Command::new("git").current_dir(dir).arg("rev-parse").arg("--short=9").arg("HEAD"), + ); GitInfo { inner: Some(Info { commit_date: ver_date.trim().to_string(), diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index df1c725758..f5c427d870 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1,11 +1,10 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. -use crate::compile::{run_cargo, std_cargo, rustc_cargo, rustc_cargo_env, - add_to_sysroot}; +use crate::compile::{run_cargo, std_cargo, rustc_cargo, add_to_sysroot}; use crate::builder::{RunConfig, Builder, Kind, ShouldRun, Step}; use crate::tool::{prepare_tool_cargo, SourceType}; use crate::{Compiler, Mode}; -use crate::cache::{INTERNER, Interned}; +use crate::cache::Interned; use std::path::PathBuf; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -97,7 +96,7 @@ impl Step for Rustc { let mut cargo = builder.cargo(compiler, Mode::Rustc, target, cargo_subcommand(builder.kind)); - rustc_cargo(builder, &mut cargo); + rustc_cargo(builder, &mut cargo, target); builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, @@ -113,55 +112,6 @@ impl Step for Rustc { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct CodegenBackend { - pub target: Interned, - pub backend: Interned, -} - -impl Step for CodegenBackend { - type Output = (); - const ONLY_HOSTS: bool = true; - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("rustc_codegen_llvm") - } - - fn make_run(run: RunConfig<'_>) { - let backend = run.builder.config.rust_codegen_backends.get(0); - let backend = backend.cloned().unwrap_or_else(|| { - INTERNER.intern_str("llvm") - }); - run.builder.ensure(CodegenBackend { - target: run.target, - backend, - }); - } - - fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(0, builder.config.build); - let target = self.target; - let backend = self.backend; - - builder.ensure(Rustc { target }); - - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, - cargo_subcommand(builder.kind)); - cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo); - - // We won't build LLVM if it's not available, as it shouldn't affect `check`. - - run_cargo(builder, - cargo, - args(builder.kind), - &codegen_backend_stamp(builder, compiler, target, backend), - vec![], - true); - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustdoc { pub target: Interned, @@ -231,16 +181,6 @@ pub fn librustc_stamp( builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp") } -/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular -/// compiler for the specified target and backend. -fn codegen_backend_stamp(builder: &Builder<'_>, - compiler: Compiler, - target: Interned, - backend: Interned) -> PathBuf { - builder.cargo_out(compiler, Mode::Codegen, target) - .join(format!(".librustc_codegen_llvm-{}-check.stamp", backend)) -} - /// Cargo's output path for rustdoc in a given stage, compiled by a particular /// compiler for the specified target. pub fn rustdoc_stamp( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 8e5fe2520c..831053bc0f 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -27,7 +27,7 @@ use crate::{Compiler, Mode, GitRepo}; use crate::native; use crate::cache::{INTERNER, Interned}; -use crate::builder::{Step, RunConfig, ShouldRun, Builder}; +use crate::builder::{Step, RunConfig, ShouldRun, Builder, Kind}; #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { @@ -113,7 +113,7 @@ impl Step for Std { } } -/// Copies third pary objects needed by various targets. +/// Copies third party objects needed by various targets. fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned) -> Vec { @@ -445,7 +445,7 @@ impl Step for Rustc { }); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build"); - rustc_cargo(builder, &mut cargo); + rustc_cargo(builder, &mut cargo, target); builder.info(&format!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, &compiler.host, target)); @@ -456,6 +456,44 @@ impl Step for Rustc { vec![], false); + // We used to build librustc_codegen_llvm as a separate step, + // which produced a dylib that the compiler would dlopen() at runtime. + // This meant that we only needed to make sure that libLLVM.so was + // installed by the time we went to run a tool using it - since + // librustc_codegen_llvm was effectively a standalone artifact, + // other crates were completely oblivious to its dependency + // on `libLLVM.so` during build time. + // + // However, librustc_codegen_llvm is now built as an ordinary + // crate during the same step as the rest of the compiler crates. + // This means that any crates depending on it will see the fact + // that it uses `libLLVM.so` as a native library, and will + // cause us to pass `-llibLLVM.so` to the linker when we link + // a binary. + // + // For `rustc` itself, this works out fine. + // During the `Assemble` step, we call `dist::maybe_install_llvm_dylib` + // to copy libLLVM.so into the `stage` directory. We then link + // the compiler binary, which will find `libLLVM.so` in the correct place. + // + // However, this is insufficient for tools that are build against stage0 + // (e.g. stage1 rustdoc). Since `Assemble` for stage0 doesn't actually do anything, + // we won't have `libLLVM.so` in the stage0 sysroot. In the past, this wasn't + // a problem - we would copy the tool binary into its correct stage directory + // (e.g. stage1 for a stage1 rustdoc built against a stage0 compiler). + // Since libLLVM.so wasn't resolved until runtime, it was fine for it to + // not exist while we were building it. + // + // To ensure that we can still build stage1 tools against a stage0 compiler, + // we explicitly copy libLLVM.so into the stage0 sysroot when building + // the stage0 compiler. This ensures that tools built against stage0 + // will see libLLVM.so at build time, making the linker happy. + if compiler.stage == 0 { + builder.info(&format!("Installing libLLVM.so to stage 0 ({})", compiler.host)); + let sysroot = builder.sysroot(compiler); + dist::maybe_install_llvm_dylib(builder, compiler.host, &sysroot); + } + builder.ensure(RustcLink { compiler: builder.compiler(compiler.stage, builder.config.build), target_compiler: compiler, @@ -464,21 +502,20 @@ impl Step for Rustc { } } -pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo) { +pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned) { cargo.arg("--features").arg(builder.rustc_features()) .arg("--manifest-path") .arg(builder.src.join("src/rustc/Cargo.toml")); - rustc_cargo_env(builder, cargo); + rustc_cargo_env(builder, cargo, target); } -pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) { +pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo.env("CFG_RELEASE", builder.rust_release()) .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("CFG_VERSION", builder.rust_version()) - .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default()) - .env("CFG_CODEGEN_BACKENDS_DIR", &builder.config.rust_codegen_backends_dir); + .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default()); let libdir_relative = builder.config.libdir_relative().unwrap_or(Path::new("lib")); cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); @@ -501,6 +538,49 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) { if builder.config.rust_verify_llvm_ir { cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); } + + // Pass down configuration from the LLVM build into the build of + // librustc_llvm and librustc_codegen_llvm. + // + // Note that this is disabled if LLVM itself is disabled or we're in a check + // build, where if we're in a check build there's no need to build all of + // LLVM and such. + if builder.config.llvm_enabled() && builder.kind != Kind::Check { + if builder.is_rust_llvm(target) { + cargo.env("LLVM_RUSTLLVM", "1"); + } + let llvm_config = builder.ensure(native::Llvm { target }); + cargo.env("LLVM_CONFIG", &llvm_config); + let target_config = builder.config.target_config.get(&target); + if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { + cargo.env("CFG_LLVM_ROOT", s); + } + // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm. + if let Some(ref s) = builder.config.llvm_ldflags { + cargo.env("LLVM_LINKER_FLAGS", s); + } + // Building with a static libstdc++ is only supported on linux right now, + // not for MSVC or macOS + if builder.config.llvm_static_stdcpp && + !target.contains("freebsd") && + !target.contains("msvc") && + !target.contains("apple") { + let file = compiler_file(builder, + builder.cxx(target).unwrap(), + target, + "libstdc++.a"); + cargo.env("LLVM_STATIC_STDCPP", file); + } + if builder.config.llvm_link_shared || builder.config.llvm_thin_lto { + cargo.env("LLVM_LINK_SHARED", "1"); + } + if builder.config.llvm_use_libcxx { + cargo.env("LLVM_USE_LIBCXX", "1"); + } + if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo { + cargo.env("LLVM_NDEBUG", "1"); + } + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -537,215 +617,6 @@ impl Step for RustcLink { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct CodegenBackend { - pub compiler: Compiler, - pub target: Interned, - pub backend: Interned, -} - -impl Step for CodegenBackend { - type Output = (); - const ONLY_HOSTS: bool = true; - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("rustc_codegen_llvm") - } - - fn make_run(run: RunConfig<'_>) { - let backend = run.builder.config.rust_codegen_backends.get(0); - let backend = backend.cloned().unwrap_or_else(|| { - INTERNER.intern_str("llvm") - }); - run.builder.ensure(CodegenBackend { - compiler: run.builder.compiler(run.builder.top_stage, run.host), - target: run.target, - backend, - }); - } - - fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; - let target = self.target; - let backend = self.backend; - - builder.ensure(Rustc { compiler, target }); - - if builder.config.keep_stage.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old codegen backend. \ - This may not behave well."); - // Codegen backends are linked separately from this step today, so we don't do - // anything here. - return; - } - - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - if compiler_to_use != compiler { - builder.ensure(CodegenBackend { - compiler: compiler_to_use, - target, - backend, - }); - return; - } - - let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); - - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build"); - cargo.arg("--manifest-path") - .arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo); - - let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); - cargo.arg("--features").arg(features); - - let tmp_stamp = out_dir.join(".tmp.stamp"); - - let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false); - if builder.config.dry_run { - return; - } - let mut files = files.into_iter() - .filter(|f| { - let filename = f.file_name().unwrap().to_str().unwrap(); - is_dylib(filename) && filename.contains("rustc_codegen_llvm-") - }); - let codegen_backend = match files.next() { - Some(f) => f, - None => panic!("no dylibs built for codegen backend?"), - }; - if let Some(f) = files.next() { - panic!("codegen backend built two dylibs:\n{}\n{}", - codegen_backend.display(), - f.display()); - } - let stamp = codegen_backend_stamp(builder, compiler, target, backend); - let codegen_backend = codegen_backend.to_str().unwrap(); - t!(fs::write(&stamp, &codegen_backend)); - } -} - -pub fn build_codegen_backend(builder: &Builder<'_>, - cargo: &mut Cargo, - compiler: &Compiler, - target: Interned, - backend: Interned) -> String { - match &*backend { - "llvm" => { - // Build LLVM for our target. This will implicitly build the - // host LLVM if necessary. - let llvm_config = builder.ensure(native::Llvm { - target, - }); - - builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", - compiler.stage, &compiler.host, target, backend)); - - // Pass down configuration from the LLVM build into the build of - // librustc_llvm and librustc_codegen_llvm. - if builder.is_rust_llvm(target) { - cargo.env("LLVM_RUSTLLVM", "1"); - } - - cargo.env("LLVM_CONFIG", &llvm_config); - let target_config = builder.config.target_config.get(&target); - if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - cargo.env("CFG_LLVM_ROOT", s); - } - // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm. - if let Some(ref s) = builder.config.llvm_ldflags { - cargo.env("LLVM_LINKER_FLAGS", s); - } - // Building with a static libstdc++ is only supported on linux and mingw right now, - // not for MSVC or macOS - if builder.config.llvm_static_stdcpp && - !target.contains("freebsd") && - !target.contains("msvc") && - !target.contains("apple") { - let file = compiler_file(builder, - builder.cxx(target).unwrap(), - target, - "libstdc++.a"); - cargo.env("LLVM_STATIC_STDCPP", file); - } - if builder.config.llvm_link_shared || builder.config.llvm_thin_lto { - cargo.env("LLVM_LINK_SHARED", "1"); - } - if builder.config.llvm_use_libcxx { - cargo.env("LLVM_USE_LIBCXX", "1"); - } - if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo { - cargo.env("LLVM_NDEBUG", "1"); - } - } - _ => panic!("unknown backend: {}", backend), - } - String::new() -} - -/// Creates the `codegen-backends` folder for a compiler that's about to be -/// assembled as a complete compiler. -/// -/// This will take the codegen artifacts produced by `compiler` and link them -/// into an appropriate location for `target_compiler` to be a functional -/// compiler. -fn copy_codegen_backends_to_sysroot(builder: &Builder<'_>, - compiler: Compiler, - target_compiler: Compiler) { - let target = target_compiler.host; - - // Note that this step is different than all the other `*Link` steps in - // that it's not assembling a bunch of libraries but rather is primarily - // moving the codegen backend into place. The codegen backend of rustc is - // not linked into the main compiler by default but is rather dynamically - // selected at runtime for inclusion. - // - // Here we're looking for the output dylib of the `CodegenBackend` step and - // we're copying that into the `codegen-backends` folder. - let dst = builder.sysroot_codegen_backends(target_compiler); - t!(fs::create_dir_all(&dst)); - - if builder.config.dry_run { - return; - } - - for backend in builder.config.rust_codegen_backends.iter() { - let stamp = codegen_backend_stamp(builder, compiler, target, *backend); - let dylib = t!(fs::read_to_string(&stamp)); - let file = Path::new(&dylib); - let filename = file.file_name().unwrap().to_str().unwrap(); - // change `librustc_codegen_llvm-xxxxxx.so` to `librustc_codegen_llvm-llvm.so` - let target_filename = { - let dash = filename.find('-').unwrap(); - let dot = filename.find('.').unwrap(); - format!("{}-{}{}", - &filename[..dash], - backend, - &filename[dot..]) - }; - builder.copy(&file, &dst.join(target_filename)); - } -} - -fn copy_lld_to_sysroot(builder: &Builder<'_>, - target_compiler: Compiler, - lld_install_root: &Path) { - let target = target_compiler.host; - - let dst = builder.sysroot_libdir(target_compiler, target) - .parent() - .unwrap() - .join("bin"); - t!(fs::create_dir_all(&dst)); - - let src_exe = exe("lld", &target); - let dst_exe = exe("rust-lld", &target); - // we prepend this bin directory to the user PATH when linking Rust binaries. To - // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. - builder.copy(&lld_install_root.join("bin").join(&src_exe), &dst.join(&dst_exe)); -} - /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. pub fn libstd_stamp( @@ -766,16 +637,6 @@ pub fn librustc_stamp( builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp") } -/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular -/// compiler for the specified target and backend. -fn codegen_backend_stamp(builder: &Builder<'_>, - compiler: Compiler, - target: Interned, - backend: Interned) -> PathBuf { - builder.cargo_out(compiler, Mode::Codegen, target) - .join(format!(".librustc_codegen_llvm-{}.stamp", backend)) -} - pub fn compiler_file( builder: &Builder<'_>, compiler: &Path, @@ -879,13 +740,6 @@ impl Step for Assemble { compiler: build_compiler, target: target_compiler.host, }); - for &backend in builder.config.rust_codegen_backends.iter() { - builder.ensure(CodegenBackend { - compiler: build_compiler, - target: target_compiler.host, - backend, - }); - } let lld_install = if builder.config.lld_enabled { Some(builder.ensure(native::Lld { @@ -911,13 +765,19 @@ impl Step for Assemble { } } - copy_codegen_backends_to_sysroot(builder, - build_compiler, - target_compiler); + let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); if let Some(lld_install) = lld_install { - copy_lld_to_sysroot(builder, target_compiler, &lld_install); + let src_exe = exe("lld", &target_compiler.host); + let dst_exe = exe("rust-lld", &target_compiler.host); + // we prepend this bin directory to the user PATH when linking Rust binaries. To + // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. + let dst = libdir.parent().unwrap().join("bin"); + t!(fs::create_dir_all(&dst)); + builder.copy(&lld_install.join("bin").join(&src_exe), &dst.join(&dst_exe)); } + // Ensure that `libLLVM.so` ends up in the newly build compiler directory, + // so that it can be found when the newly built `rustc` is run. dist::maybe_install_llvm_dylib(builder, target_compiler.host, &sysroot); // Link the compiler binary itself into place diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d1bdfa0a76..5f2ef01bd5 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -105,7 +105,6 @@ pub struct Config { pub rust_optimize_tests: bool, pub rust_dist_src: bool, pub rust_codegen_backends: Vec>, - pub rust_codegen_backends_dir: String, pub rust_verify_llvm_ir: bool, pub rust_remap_debuginfo: bool, @@ -316,7 +315,6 @@ struct Rust { dist_src: Option, save_toolstates: Option, codegen_backends: Option>, - codegen_backends_dir: Option, lld: Option, llvm_tools: Option, lldb: Option, @@ -372,7 +370,6 @@ impl Config { config.ignore_git = false; config.rust_dist_src = true; config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")]; - config.rust_codegen_backends_dir = "codegen-backends".to_owned(); config.deny_warnings = true; config.missing_tools = false; @@ -575,8 +572,6 @@ impl Config { .collect(); } - set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone()); - config.rust_codegen_units = rust.codegen_units.map(threads_from_config); config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); } @@ -647,6 +642,20 @@ impl Config { config } + /// Try to find the relative path of `bindir`, otherwise return it in full. + pub fn bindir_relative(&self) -> &Path { + let bindir = &self.bindir; + if bindir.is_absolute() { + // Try to make it relative to the prefix. + if let Some(prefix) = &self.prefix { + if let Ok(stripped) = bindir.strip_prefix(prefix) { + return stripped; + } + } + } + bindir + } + /// Try to find the relative path of `libdir`. pub fn libdir_relative(&self) -> Option<&Path> { let libdir = self.libdir.as_ref()?; diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 67907bc8cb..02533944fc 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -498,16 +498,6 @@ impl Step for Rustc { } } - // Copy over the codegen backends - let backends_src = builder.sysroot_codegen_backends(compiler); - let backends_rel = backends_src.strip_prefix(&src).unwrap() - .strip_prefix(builder.sysroot_libdir_relative(compiler)).unwrap(); - // Don't use custom libdir here because ^lib/ will be resolved again with installer - let backends_dst = image.join("lib").join(&backends_rel); - - t!(fs::create_dir_all(&backends_dst)); - builder.cp_r(&backends_src, &backends_dst); - // Copy libLLVM.so to the lib dir as well, if needed. While not // technically needed by rustc itself it's needed by lots of other // components like the llvm tools and LLD. LLD is included below and @@ -616,6 +606,7 @@ impl Step for DebuggerScripts { cp_debugger_script("natvis/intrinsic.natvis"); cp_debugger_script("natvis/liballoc.natvis"); cp_debugger_script("natvis/libcore.natvis"); + cp_debugger_script("natvis/libstd.natvis"); } else { cp_debugger_script("debugger_pretty_printers_common.py"); @@ -2133,6 +2124,10 @@ impl Step for HashSign { // Maybe add libLLVM.so to the lib-dir. It will only have been built if // LLVM tools are linked dynamically. +// +// We add this to both the libdir of the rustc binary itself (for it to load at +// runtime) and also to the target directory so it can find it at link-time. +// // Note: This function does no yet support Windows but we also don't support // linking LLVM tools dynamically on Windows yet. pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, @@ -2141,13 +2136,19 @@ pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, let src_libdir = builder .llvm_out(target) .join("lib"); - let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib"); - t!(fs::create_dir_all(&dst_libdir)); + let dst_libdir1 = sysroot.join("lib/rustlib").join(&*target).join("lib"); + let dst_libdir2 = sysroot.join(builder.sysroot_libdir_relative(Compiler { + stage: 1, + host: target, + })); + t!(fs::create_dir_all(&dst_libdir1)); + t!(fs::create_dir_all(&dst_libdir2)); if target.contains("apple-darwin") { let llvm_dylib_path = src_libdir.join("libLLVM.dylib"); if llvm_dylib_path.exists() { - builder.install(&llvm_dylib_path, &dst_libdir, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir1, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir2, 0o644); } return } @@ -2163,7 +2164,8 @@ pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, }); - builder.install(&llvm_dylib_path, &dst_libdir, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir1, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir2, 0o644); } } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 4ee8cd2485..608cee0a80 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -433,7 +433,7 @@ impl Step for Std { builder.info(&format!("Documenting stage{} std ({})", stage, target)); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler_for(stage, builder.config.build, target); + let compiler = builder.compiler(stage, builder.config.build); builder.ensure(compile::Std { compiler, target }); let out_dir = builder.stage_out(compiler, Mode::Std) @@ -541,7 +541,7 @@ impl Step for Rustc { // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden"); - compile::rustc_cargo(builder, &mut cargo); + compile::rustc_cargo(builder, &mut cargo, target); // Only include compiler crates, no dependencies of those, such as `libc`. cargo.arg("--no-deps"); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index d9580b5981..7b49cc0a92 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -448,12 +448,12 @@ Arguments: Flags { verbose: matches.opt_count("verbose"), - stage: matches.opt_str("stage").map(|j| j.parse().unwrap()), + stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")), dry_run: matches.opt_present("dry-run"), on_fail: matches.opt_str("on-fail"), rustc_error_format: matches.opt_str("error-format"), keep_stage: matches.opt_strs("keep-stage") - .into_iter().map(|j| j.parse().unwrap()) + .into_iter().map(|j| j.parse().expect("`keep-stage` should be a number")) .collect(), host: split(&matches.opt_strs("host")) .into_iter() @@ -464,7 +464,7 @@ Arguments: .map(|x| INTERNER.intern_string(x)) .collect::>(), config: cfg_file, - jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), + jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")), cmd, incremental: matches.opt_present("incremental"), exclude: split(&matches.opt_strs("exclude")) diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 384219c38f..f8734ebdf4 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -260,7 +260,7 @@ install!((self, builder, _config), }; Rustc, "src/librustc", true, only_hosts: true, { builder.ensure(dist::Rustc { - compiler: self.compiler, + compiler: builder.compiler(builder.top_stage, self.target), }); install_rustc(builder, self.compiler.stage, self.target); }; diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 39d7ea922b..080bef6853 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -169,7 +169,6 @@ mod job { pub use crate::config::Config; use crate::flags::Subcommand; use crate::cache::{Interned, INTERNER}; -use crate::toolstate::ToolState; const LLVM_TOOLS: &[&str] = &[ "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility @@ -501,6 +500,9 @@ impl Build { if self.config.jemalloc { features.push_str("jemalloc"); } + if self.config.llvm_enabled() { + features.push_str(" llvm"); + } features } @@ -806,11 +808,8 @@ impl Build { .and_then(|c| c.linker.as_ref()) { Some(linker) } else if target != self.config.build && - !target.contains("msvc") && - !target.contains("emscripten") && - !target.contains("wasm32") && - !target.contains("nvptx") && - !target.contains("fuchsia") { + util::use_host_linker(&target) && + !target.contains("msvc") { Some(self.cc(target)) } else { None @@ -1073,32 +1072,6 @@ impl Build { } } - /// Updates the actual toolstate of a tool. - /// - /// The toolstates are saved to the file specified by the key - /// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be - /// done. The file is updated immediately after this function completes. - pub fn save_toolstate(&self, tool: &str, state: ToolState) { - if let Some(ref path) = self.config.save_toolstates { - if let Some(parent) = path.parent() { - // Ensure the parent directory always exists - t!(std::fs::create_dir_all(parent)); - } - let mut file = t!(fs::OpenOptions::new() - .create(true) - .read(true) - .write(true) - .open(path)); - - let mut current_toolstates: HashMap, ToolState> = - serde_json::from_reader(&mut file).unwrap_or_default(); - current_toolstates.insert(tool.into(), state); - t!(file.seek(SeekFrom::Start(0))); - t!(file.set_len(0)); - t!(serde_json::to_writer(file, ¤t_toolstates)); - } - } - fn in_tree_crates(&self, root: &str) -> Vec<&Crate> { let mut ret = Vec::new(); let mut list = vec![INTERNER.intern_str(root)]; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 2e89fd5398..be13b9aa2e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -294,11 +294,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { let mut parts = version.split('.').take(2) .filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) { - if major >= 6 { + if major >= 7 { return } } - panic!("\n\nbad LLVM version: {}, need >=6.0\n\n", version) + panic!("\n\nbad LLVM version: {}, need >=7.0\n\n", version) } fn configure_cmake(builder: &Builder<'_>, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 60f0dccdb0..f3b2a73d3c 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -570,7 +570,12 @@ impl Step for Clippy { let host_libs = builder .stage_out(compiler, Mode::ToolRustc) .join(builder.cargo_dir()); + let target_libs = builder + .stage_out(compiler, Mode::ToolRustc) + .join(&self.host) + .join(builder.cargo_dir()); cargo.env("HOST_LIBS", host_libs); + cargo.env("TARGET_LIBS", target_libs); // clippy tests need to find the driver cargo.env("CLIPPY_DRIVER_PATH", clippy); @@ -1768,7 +1773,7 @@ impl Step for Crate { } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); - compile::rustc_cargo(builder, &mut cargo); + compile::rustc_cargo(builder, &mut cargo, target); } _ => panic!("can only test libraries"), }; diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index e86209be91..a6d9ef38e5 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -1,4 +1,28 @@ use serde::{Deserialize, Serialize}; +use build_helper::t; +use std::time; +use std::fs; +use std::io::{Seek, SeekFrom}; +use std::collections::HashMap; +use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use std::fmt; +use std::process::Command; +use std::path::PathBuf; +use std::env; + +// Each cycle is 42 days long (6 weeks); the last week is 35..=42 then. +const BETA_WEEK_START: u64 = 35; + +#[cfg(linux)] +const OS: Option<&str> = Some("linux"); + +#[cfg(windows)] +const OS: Option<&str> = Some("windows"); + +#[cfg(all(not(linux), not(windows)))] +const OS: Option<&str> = None; + +type ToolstateData = HashMap, ToolState>; #[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] @@ -12,9 +36,392 @@ pub enum ToolState { BuildFail = 0, } +impl fmt::Display for ToolState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", match self { + ToolState::TestFail => "test-fail", + ToolState::TestPass => "test-pass", + ToolState::BuildFail => "build-fail", + }) + } +} + impl Default for ToolState { fn default() -> Self { // err on the safe side ToolState::BuildFail } } + +/// Number of days after the last promotion of beta. +/// Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens. +/// The Wednesday after this has value 0. +/// We track this value to prevent regressing tools in the last week of the 6-week cycle. +fn days_since_beta_promotion() -> u64 { + let since_epoch = t!(time::SystemTime::UNIX_EPOCH.elapsed()); + (since_epoch.as_secs() / 86400 - 20) % 42 +} + +// These tools must test-pass on the beta/stable channels. +// +// On the nightly channel, their build step must be attempted, but they may not +// be able to build successfully. +static STABLE_TOOLS: &[(&str, &str)] = &[ + ("book", "src/doc/book"), + ("nomicon", "src/doc/nomicon"), + ("reference", "src/doc/reference"), + ("rust-by-example", "src/doc/rust-by-example"), + ("edition-guide", "src/doc/edition-guide"), + ("rls", "src/tools/rls"), + ("rustfmt", "src/tools/rustfmt"), + ("clippy-driver", "src/tools/clippy"), +]; + +// These tools are permitted to not build on the beta/stable channels. +// +// We do require that we checked whether they build or not on the tools builder, +// though, as otherwise we will be unable to file an issue if they start +// failing. +static NIGHTLY_TOOLS: &[(&str, &str)] = &[ + ("miri", "src/tools/miri"), + ("embedded-book", "src/doc/embedded-book"), + ("rustc-guide", "src/doc/rustc-guide"), +]; + +fn print_error(tool: &str, submodule: &str) { + eprintln!(""); + eprintln!("We detected that this PR updated '{}', but its tests failed.", tool); + eprintln!(""); + eprintln!("If you do intend to update '{}', please check the error messages above and", tool); + eprintln!("commit another update."); + eprintln!(""); + eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool); + eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule); + eprintln!("proper steps."); + std::process::exit(3); +} + +fn check_changed_files(toolstates: &HashMap, ToolState>) { + // Changed files + let output = std::process::Command::new("git") + .arg("diff") + .arg("--name-status") + .arg("HEAD") + .arg("HEAD^") + .output(); + let output = match output { + Ok(o) => o, + Err(e) => { + eprintln!("Failed to get changed files: {:?}", e); + std::process::exit(1); + } + }; + + let output = t!(String::from_utf8(output.stdout)); + + for (tool, submodule) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) { + let changed = output.lines().any(|l| { + l.starts_with("M") && l.ends_with(submodule) + }); + eprintln!("Verifying status of {}...", tool); + if !changed { + continue; + } + + eprintln!("This PR updated '{}', verifying if status is 'test-pass'...", submodule); + if toolstates[*tool] != ToolState::TestPass { + print_error(tool, submodule); + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ToolStateCheck; + +impl Step for ToolStateCheck { + type Output = (); + + /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. + /// + /// This tool in `src/tools` will verify the validity of all our links in the + /// documentation to ensure we don't have a bunch of dead ones. + fn run(self, builder: &Builder<'_>) { + if builder.config.dry_run { + return; + } + + let days_since_beta_promotion = days_since_beta_promotion(); + let in_beta_week = days_since_beta_promotion >= BETA_WEEK_START; + let is_nightly = !(builder.config.channel == "beta" || builder.config.channel == "stable"); + let toolstates = builder.toolstates(); + + let mut did_error = false; + + for (tool, _) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) { + if !toolstates.contains_key(*tool) { + did_error = true; + eprintln!("error: Tool `{}` was not recorded in tool state.", tool); + } + } + + if did_error { + std::process::exit(1); + } + + check_changed_files(&toolstates); + + for (tool, _) in STABLE_TOOLS.iter() { + let state = toolstates[*tool]; + + if state != ToolState::TestPass { + if !is_nightly { + did_error = true; + eprintln!("error: Tool `{}` should be test-pass but is {}", tool, state); + } else if in_beta_week { + did_error = true; + eprintln!("error: Tool `{}` should be test-pass but is {} during beta week.", + tool, state); + } + } + } + + if did_error { + std::process::exit(1); + } + + if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() { + commit_toolstate_change(&toolstates, in_beta_week); + } + } + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("check-tools") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(ToolStateCheck); + } +} + +impl Builder<'_> { + fn toolstates(&self) -> HashMap, ToolState> { + if let Some(ref path) = self.config.save_toolstates { + if let Some(parent) = path.parent() { + // Ensure the parent directory always exists + t!(std::fs::create_dir_all(parent)); + } + let mut file = t!(fs::OpenOptions::new() + .create(true) + .write(true) + .read(true) + .open(path)); + + serde_json::from_reader(&mut file).unwrap_or_default() + } else { + Default::default() + } + } + + /// Updates the actual toolstate of a tool. + /// + /// The toolstates are saved to the file specified by the key + /// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be + /// done. The file is updated immediately after this function completes. + pub fn save_toolstate(&self, tool: &str, state: ToolState) { + if let Some(ref path) = self.config.save_toolstates { + if let Some(parent) = path.parent() { + // Ensure the parent directory always exists + t!(std::fs::create_dir_all(parent)); + } + let mut file = t!(fs::OpenOptions::new() + .create(true) + .read(true) + .write(true) + .open(path)); + + let mut current_toolstates: HashMap, ToolState> = + serde_json::from_reader(&mut file).unwrap_or_default(); + current_toolstates.insert(tool.into(), state); + t!(file.seek(SeekFrom::Start(0))); + t!(file.set_len(0)); + t!(serde_json::to_writer(file, ¤t_toolstates)); + } + } +} + +/// This function `commit_toolstate_change` provides functionality for pushing a change +/// to the `rust-toolstate` repository. +/// +/// The function relies on a GitHub bot user, which should have a Personal access +/// token defined in the environment variable $TOOLSTATE_REPO_ACCESS_TOKEN. If for +/// some reason you need to change the token, please update the Azure Pipelines +/// variable group. +/// +/// 1. Generate a new Personal access token: +/// +/// * Login to the bot account, and go to Settings -> Developer settings -> +/// Personal access tokens +/// * Click "Generate new token" +/// * Enable the "public_repo" permission, then click "Generate token" +/// * Copy the generated token (should be a 40-digit hexadecimal number). +/// Save it somewhere secure, as the token would be gone once you leave +/// the page. +/// +/// 2. Update the variable group in Azure Pipelines +/// +/// * Ping a member of the infrastructure team to do this. +/// +/// 4. Replace the email address below if the bot account identity is changed +/// +/// * See +/// if a private email by GitHub is wanted. +fn commit_toolstate_change( + current_toolstate: &ToolstateData, + in_beta_week: bool, +) { + fn git_config(key: &str, value: &str) { + let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status(); + let success = match status { + Ok(s) => s.success(), + Err(_) => false, + }; + if !success { + panic!("git config key={} value={} successful (status: {:?})", key, value, status); + } + } + + // If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date + // as well. + git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com"); + git_config("user.name", "Rust Toolstate Update"); + git_config("credential.helper", "store"); + + let credential = format!( + "https://{}:x-oauth-basic@github.com\n", + t!(env::var("TOOLSTATE_REPO_ACCESS_TOKEN")), + ); + let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials"); + t!(fs::write(&git_credential_path, credential)); + + let status = Command::new("git").arg("clone") + .arg("--depth=1") + .arg(t!(env::var("TOOLSTATE_REPO"))) + .status(); + let success = match status { + Ok(s) => s.success(), + Err(_) => false, + }; + if !success { + panic!("git clone successful (status: {:?})", status); + } + + let old_toolstate = t!(fs::read("rust-toolstate/_data/latest.json")); + let old_toolstate: Vec = t!(serde_json::from_slice(&old_toolstate)); + + let message = format!("({} CI update)", OS.expect("linux/windows only")); + let mut success = false; + for _ in 1..=5 { + // Update the toolstate results (the new commit-to-toolstate mapping) in the toolstate repo. + change_toolstate(¤t_toolstate, &old_toolstate, in_beta_week); + + // `git commit` failing means nothing to commit. + let status = t!(Command::new("git") + .current_dir("rust-toolstate") + .arg("commit") + .arg("-a") + .arg("-m") + .arg(&message) + .status()); + if !status.success() { + success = true; + break; + } + + let status = t!(Command::new("git") + .current_dir("rust-toolstate") + .arg("push") + .arg("origin") + .arg("master") + .status()); + // If we successfully push, exit. + if status.success() { + success = true; + break; + } + eprintln!("Sleeping for 3 seconds before retrying push"); + std::thread::sleep(std::time::Duration::from_secs(3)); + let status = t!(Command::new("git") + .current_dir("rust-toolstate") + .arg("fetch") + .arg("origin") + .arg("master") + .status()); + assert!(status.success()); + let status = t!(Command::new("git") + .current_dir("rust-toolstate") + .arg("reset") + .arg("--hard") + .arg("origin/master") + .status()); + assert!(status.success()); + } + + if !success { + panic!("Failed to update toolstate repository with new data"); + } +} + +fn change_toolstate( + current_toolstate: &ToolstateData, + old_toolstate: &[RepoState], + in_beta_week: bool, +) { + let mut regressed = false; + for repo_state in old_toolstate { + let tool = &repo_state.tool; + let state = if cfg!(linux) { + &repo_state.linux + } else if cfg!(windows) { + &repo_state.windows + } else { + unimplemented!() + }; + let new_state = current_toolstate[tool.as_str()]; + + if new_state != *state { + eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state); + if (new_state as u8) < (*state as u8) { + if !["rustc-guide", "miri", "embedded-book"].contains(&tool.as_str()) { + regressed = true; + } + } + } + } + + if regressed && in_beta_week { + std::process::exit(1); + } + + let commit = t!(std::process::Command::new("git") + .arg("rev-parse") + .arg("HEAD") + .output()); + let commit = t!(String::from_utf8(commit.stdout)); + + let toolstate_serialized = t!(serde_json::to_string(¤t_toolstate)); + + let history_path = format!("rust-toolstate/history/{}.tsv", OS.expect("linux/windows only")); + let mut file = t!(fs::read_to_string(&history_path)); + let end_of_first_line = file.find('\n').unwrap(); + file.insert_str(end_of_first_line, &format!("{}\t{}\n", commit, toolstate_serialized)); + t!(fs::write(&history_path, file)); +} + +#[derive(Debug, Serialize, Deserialize)] +struct RepoState { + tool: String, + windows: ToolState, + linux: ToolState, + commit: String, + datetime: String, +} diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 98ae7b692b..6824b7a58c 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -15,6 +15,7 @@ use build_helper::t; use crate::config::Config; use crate::builder::Builder; +use crate::cache::Interned; /// Returns the `name` as the filename of a static library for `target`. pub fn staticlib(name: &str, target: &str) -> String { @@ -262,6 +263,8 @@ pub enum CiEnv { None, /// The Azure Pipelines environment, for Linux (including Docker), Windows, and macOS builds. AzurePipelines, + /// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds. + GitHubActions, } impl CiEnv { @@ -269,6 +272,8 @@ impl CiEnv { pub fn current() -> CiEnv { if env::var("TF_BUILD").ok().map_or(false, |e| &*e == "True") { CiEnv::AzurePipelines + } else if env::var("GITHUB_ACTIONS").ok().map_or(false, |e| &*e == "true") { + CiEnv::GitHubActions } else { CiEnv::None } @@ -302,3 +307,15 @@ pub fn forcing_clang_based_tests() -> bool { false } } + +pub fn use_host_linker(target: &Interned) -> bool { + // FIXME: this information should be gotten by checking the linker flavor + // of the rustc target + !( + target.contains("emscripten") || + target.contains("wasm32") || + target.contains("nvptx") || + target.contains("fortanix") || + target.contains("fuchsia") + ) +} diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 271c325854..5248e41725 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -18,137 +18,47 @@ jobs: - template: steps/run.yml strategy: matrix: - x86_64-gnu-llvm-6.0: - IMAGE: x86_64-gnu-llvm-6.0 + x86_64-gnu-llvm-7: RUST_BACKTRACE: 1 - - dist-x86_64-linux: - IMAGE: dist-x86_64-linux - DEPLOY: 1 - - # "alternate" deployments, these are "nightlies" but have LLVM assertions - # turned on, they're deployed to a different location primarily for - # additional testing. + dist-x86_64-linux: {} dist-x86_64-linux-alt: IMAGE: dist-x86_64-linux - DEPLOY_ALT: 1 - - # Linux builders, remaining docker images - arm-android: - IMAGE: arm-android - - armhf-gnu: - IMAGE: armhf-gnu - - dist-various-1: - IMAGE: dist-various-1 - DEPLOY: 1 - - dist-various-2: - IMAGE: dist-various-2 - DEPLOY: 1 - - dist-aarch64-linux: - IMAGE: dist-aarch64-linux - DEPLOY: 1 - - dist-android: - IMAGE: dist-android - DEPLOY: 1 - - dist-arm-linux: - IMAGE: dist-arm-linux - DEPLOY: 1 - - dist-armhf-linux: - IMAGE: dist-armhf-linux - DEPLOY: 1 - - dist-armv7-linux: - IMAGE: dist-armv7-linux - DEPLOY: 1 - - dist-i586-gnu-i586-i686-musl: - IMAGE: dist-i586-gnu-i586-i686-musl - DEPLOY: 1 - - dist-i686-freebsd: - IMAGE: dist-i686-freebsd - DEPLOY: 1 - - dist-i686-linux: - IMAGE: dist-i686-linux - DEPLOY: 1 - - dist-mips-linux: - IMAGE: dist-mips-linux - DEPLOY: 1 - - dist-mips64-linux: - IMAGE: dist-mips64-linux - DEPLOY: 1 - - dist-mips64el-linux: - IMAGE: dist-mips64el-linux - DEPLOY: 1 - - dist-mipsel-linux: - IMAGE: dist-mipsel-linux - DEPLOY: 1 - - dist-powerpc-linux: - IMAGE: dist-powerpc-linux - DEPLOY: 1 - - dist-powerpc64-linux: - IMAGE: dist-powerpc64-linux - DEPLOY: 1 - - dist-powerpc64le-linux: - IMAGE: dist-powerpc64le-linux - DEPLOY: 1 - - dist-s390x-linux: - IMAGE: dist-s390x-linux - DEPLOY: 1 - - dist-x86_64-freebsd: - IMAGE: dist-x86_64-freebsd - DEPLOY: 1 - - dist-x86_64-musl: - IMAGE: dist-x86_64-musl - DEPLOY: 1 - - dist-x86_64-netbsd: - IMAGE: dist-x86_64-netbsd - DEPLOY: 1 - - i686-gnu: - IMAGE: i686-gnu - i686-gnu-nopt: - IMAGE: i686-gnu-nopt - test-various: - IMAGE: test-various - wasm32: - IMAGE: wasm32 - x86_64-gnu: - IMAGE: x86_64-gnu - x86_64-gnu-full-bootstrap: - IMAGE: x86_64-gnu-full-bootstrap - x86_64-gnu-aux: - IMAGE: x86_64-gnu-aux + arm-android: {} + armhf-gnu: {} + dist-various-1: {} + dist-various-2: {} + dist-aarch64-linux: {} + dist-android: {} + dist-arm-linux: {} + dist-armhf-linux: {} + dist-armv7-linux: {} + dist-i586-gnu-i586-i686-musl: {} + dist-i686-freebsd: {} + dist-i686-linux: {} + dist-mips-linux: {} + dist-mips64-linux: {} + dist-mips64el-linux: {} + dist-mipsel-linux: {} + dist-powerpc-linux: {} + dist-powerpc64-linux: {} + dist-powerpc64le-linux: {} + dist-s390x-linux: {} + dist-x86_64-freebsd: {} + dist-x86_64-musl: {} + dist-x86_64-netbsd: {} + i686-gnu: {} + i686-gnu-nopt: {} + test-various: {} + wasm32: {} + x86_64-gnu: {} + x86_64-gnu-full-bootstrap: {} + x86_64-gnu-aux: {} x86_64-gnu-tools: - IMAGE: x86_64-gnu-tools DEPLOY_TOOLSTATES_JSON: toolstates-linux.json - x86_64-gnu-debug: - IMAGE: x86_64-gnu-debug - x86_64-gnu-nopt: - IMAGE: x86_64-gnu-nopt - x86_64-gnu-distcheck: - IMAGE: x86_64-gnu-distcheck - mingw-check: - IMAGE: mingw-check + x86_64-gnu-debug: {} + x86_64-gnu-nopt: {} + x86_64-gnu-distcheck: {} + mingw-check: {} - job: macOS timeoutInMinutes: 600 @@ -176,7 +86,6 @@ jobs: dist-x86_64-apple: SCRIPT: ./x.py dist RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc - DEPLOY: 1 RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 @@ -186,7 +95,6 @@ jobs: dist-x86_64-apple-alt: SCRIPT: ./x.py dist RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc - DEPLOY_ALT: 1 RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 @@ -204,7 +112,6 @@ jobs: dist-i686-apple: SCRIPT: ./x.py dist RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --set rust.jemalloc - DEPLOY: 1 RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 NO_LLVM_ASSERTIONS: 1 @@ -223,25 +130,21 @@ jobs: matrix: # 32/64 bit MSVC tests x86_64-msvc-1: - MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 x86_64-msvc-2: - MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-2 i686-msvc-1: - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-subset-1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 i686-msvc-2: - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-subset-2 # FIXME(#59637) @@ -249,11 +152,9 @@ jobs: NO_LLVM_ASSERTIONS: 1 # MSVC aux tests x86_64-msvc-aux: - MSYS_BITS: 64 RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc x86_64-msvc-cargo: - MSYS_BITS: 64 SCRIPT: python x.py test src/tools/cargotest src/tools/cargo RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc VCVARS_BAT: vcvars64.bat @@ -262,10 +163,8 @@ jobs: NO_LLVM_ASSERTIONS: 1 # MSVC tools tests x86_64-msvc-tools: - MSYS_BITS: 64 - SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json - DEPLOY_TOOLSTATES_JSON: toolstates-windows.json # 32/64-bit MinGW builds. # @@ -281,83 +180,57 @@ jobs: # came from the mingw-w64 SourceForge download site. Unfortunately # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. i686-mingw-1: - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu SCRIPT: make ci-mingw-subset-1 - MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 + CUSTOM_MINGW: 1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 i686-mingw-2: - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu SCRIPT: make ci-mingw-subset-2 - MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 + CUSTOM_MINGW: 1 x86_64-mingw-1: - MSYS_BITS: 64 SCRIPT: make ci-mingw-subset-1 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 + CUSTOM_MINGW: 1 # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 x86_64-mingw-2: - MSYS_BITS: 64 SCRIPT: make ci-mingw-subset-2 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 + CUSTOM_MINGW: 1 # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: > + RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc --enable-full-tools --enable-profiler SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 dist-i686-msvc: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: > + RUST_CONFIGURE_ARGS: >- --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-full-tools --enable-profiler SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 dist-i686-mingw: - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler SCRIPT: python x.py dist - MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 + CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 dist-x86_64-mingw: - MSYS_BITS: 64 SCRIPT: python x.py dist RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler - MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 + CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 # "alternate" deployment, see .travis.yml for more info dist-x86_64-msvc-alt: - MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler SCRIPT: python x.py dist - DEPLOY_ALT: 1 diff --git a/src/ci/azure-pipelines/master.yml b/src/ci/azure-pipelines/master.yml index e2baa923d9..9c5a15a3cf 100644 --- a/src/ci/azure-pipelines/master.yml +++ b/src/ci/azure-pipelines/master.yml @@ -16,10 +16,7 @@ steps: - checkout: self fetchDepth: 2 -- script: | - export MESSAGE_FILE=$(mktemp -t msg.XXXXXX) - . src/ci/docker/x86_64-gnu-tools/repo.sh - commit_toolstate_change "$MESSAGE_FILE" "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN" +- script: src/ci/publish_toolstate.sh displayName: Publish toolstate env: TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN) diff --git a/src/ci/azure-pipelines/pr.yml b/src/ci/azure-pipelines/pr.yml index 566e654fdb..1f0be53677 100644 --- a/src/ci/azure-pipelines/pr.yml +++ b/src/ci/azure-pipelines/pr.yml @@ -18,10 +18,7 @@ jobs: - template: steps/run.yml strategy: matrix: - x86_64-gnu-llvm-6.0: - IMAGE: x86_64-gnu-llvm-6.0 - mingw-check: - IMAGE: mingw-check + x86_64-gnu-llvm-7: {} + mingw-check: {} x86_64-gnu-tools: - IMAGE: x86_64-gnu-tools CI_ONLY_WHEN_SUBMODULES_CHANGED: 1 diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index cef2d23560..c39f75aba8 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -8,6 +8,13 @@ steps: +# Configure our CI_JOB_NAME variable which log analyzers can use for the main +# step to see what's going on. +- bash: | + builder=$(echo $AGENT_JOBNAME | cut -d ' ' -f 2) + echo "##vso[task.setvariable variable=CI_JOB_NAME]$builder" + displayName: Configure Job Name + # Disable automatic line ending conversion, which is enabled by default on # Azure's Windows image. Having the conversion enabled caused regressions both # in our test suite (it broke miri tests) and in the ecosystem, since we @@ -21,51 +28,42 @@ steps: - checkout: self fetchDepth: 2 +- bash: src/ci/scripts/setup-environment.sh + displayName: Setup environment + +- bash: src/ci/scripts/clean-disk.sh + displayName: Clean disk + - bash: src/ci/scripts/should-skip-this.sh displayName: Decide whether to run this job -# Spawn a background process to collect CPU usage statistics which we'll upload -# at the end of the build. See the comments in the script here for more -# information. -- bash: python src/ci/cpu-usage-over-time.py &> cpu-usage.csv & - displayName: "Collect CPU-usage statistics in the background" +- bash: src/ci/scripts/collect-cpu-stats.sh + displayName: Collect CPU-usage statistics in the background - bash: src/ci/scripts/dump-environment.sh displayName: Show the current environment - bash: src/ci/scripts/install-sccache.sh - env: - AGENT_OS: $(Agent.OS) displayName: Install sccache condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/install-clang.sh - env: - AGENT_OS: $(Agent.OS) displayName: Install clang condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/switch-xcode.sh - env: - AGENT_OS: $(Agent.OS) displayName: Switch to Xcode 9.3 condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/install-wix.sh - env: - AGENT_OS: $(Agent.OS) displayName: Install wix condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/install-innosetup.sh - env: - AGENT_OS: $(Agent.OS) displayName: Install InnoSetup condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/windows-symlink-build-dir.sh - env: - AGENT_OS: $(Agent.OS) displayName: Ensure the build happens on C:\ instead of D:\ condition: and(succeeded(), not(variables.SKIP_JOB)) @@ -74,35 +72,22 @@ steps: condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/install-msys2.sh - env: - AGENT_OS: $(Agent.OS) - SYSTEM_WORKFOLDER: $(System.Workfolder) displayName: Install msys2 condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/install-msys2-packages.sh - env: - AGENT_OS: $(Agent.OS) - SYSTEM_WORKFOLDER: $(System.Workfolder) displayName: Install msys2 packages condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/install-mingw.sh - env: - AGENT_OS: $(Agent.OS) - SYSTEM_WORKFOLDER: $(System.Workfolder) displayName: Install MinGW condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/install-ninja.sh - env: - AGENT_OS: $(Agent.OS) displayName: Install ninja condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/enable-docker-ipv6.sh - env: - AGENT_OS: $(Agent.OS) displayName: Enable IPv6 on Docker condition: and(succeeded(), not(variables.SKIP_JOB)) @@ -116,67 +101,22 @@ steps: condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/checkout-submodules.sh - env: - AGENT_OS: $(Agent.OS) displayName: Checkout submodules condition: and(succeeded(), not(variables.SKIP_JOB)) - bash: src/ci/scripts/verify-line-endings.sh - env: - AGENT_OS: $(Agent.OS) displayName: Verify line endings condition: and(succeeded(), not(variables.SKIP_JOB)) # Ensure the `aws` CLI is installed so we can deploy later on, cache docker # images, etc. - bash: src/ci/scripts/install-awscli.sh - env: - AGENT_OS: $(Agent.OS) condition: and(succeeded(), not(variables.SKIP_JOB)) displayName: Install awscli -# Configure our CI_JOB_NAME variable which log analyzers can use for the main -# step to see what's going on. -- bash: | - builder=$(echo $AGENT_JOBNAME | cut -d ' ' -f 2) - echo "##vso[task.setvariable variable=CI_JOB_NAME]$builder" - displayName: Configure Job Name - -# As a quick smoke check on the otherwise very fast mingw-check linux builder -# check our own internal scripts. -- bash: | - set -e - git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git - cd rust-toolstate - python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "" - # Only check maintainers if this build is supposed to publish toolstate. - # Builds that are not supposed to publish don't have the access token. - if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then - TOOLSTATE_VALIDATE_MAINTAINERS_REPO=rust-lang/rust python2.7 "${BUILD_SOURCESDIRECTORY}/src/tools/publish_toolstate.py" - fi - cd .. - rm -rf rust-toolstate - env: - TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN) - condition: and(succeeded(), not(variables.SKIP_JOB), eq(variables['IMAGE'], 'mingw-check')) - displayName: Verify the publish_toolstate script works - -- bash: | - set -e - # Remove any preexisting rustup installation since it can interfere - # with the cargotest step and its auto-detection of things like Clippy in - # the environment - rustup self uninstall -y || true - if [ "$IMAGE" = "" ]; then - src/ci/run.sh - else - src/ci/docker/run.sh $IMAGE - fi - #timeoutInMinutes: 180 +- bash: src/ci/scripts/run-build-from-ci.sh timeoutInMinutes: 600 env: - CI: true - SRC: . AWS_ACCESS_KEY_ID: $(SCCACHE_AWS_ACCESS_KEY_ID) AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN) diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml index c919b1023a..b6177b2cc9 100644 --- a/src/ci/azure-pipelines/try.yml +++ b/src/ci/azure-pipelines/try.yml @@ -14,13 +14,9 @@ jobs: - template: steps/run.yml strategy: matrix: - dist-x86_64-linux: - IMAGE: dist-x86_64-linux - DEPLOY: 1 - + dist-x86_64-linux: {} dist-x86_64-linux-alt: IMAGE: dist-x86_64-linux - DEPLOY_ALT: 1 # The macOS and Windows builds here are currently disabled due to them not being # overly necessary on `try` builds. We also don't actually have anything that @@ -72,7 +68,6 @@ jobs: # DEPLOY: 1 # # dist-x86_64-msvc-alt: -# MSYS_BITS: 64 # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler # SCRIPT: python x.py dist # DEPLOY_ALT: 1 diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index a2d83eca24..872f2c3467 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -16,6 +16,13 @@ for example: Images will output artifacts in an `obj` dir at the root of a repository. +**NOTE**: Re-using the same `obj` dir with different docker images with +the same target triple (e.g. `dist-x86_64-linux` and `dist-various-1`) +may result in strange linker errors, due shared library versions differing between platforms. + +If you encounter any issues when using multiple Docker images, try deleting your `obj` directory +before running your command. + ## Filesystem layout - Each directory, excluding `scripts` and `disabled`, corresponds to a docker image diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index 9493b33698..5373612279 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -72,7 +72,7 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static # TODO: What is this?! # Source of the file: https://github.com/vfdev-5/qemu-rpi2-vexpress/raw/master/vexpress-v2p-ca15-tc1.dtb -RUN curl -O https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/vexpress-v2p-ca15-tc1.dtb +RUN curl -O https://ci-mirrors.rust-lang.org/rustc/vexpress-v2p-ca15-tc1.dtb COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh index ae737d9677..fb067a79a5 100644 --- a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh +++ b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh @@ -1,7 +1,7 @@ set -ex # Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz -url="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/crosstool-ng-1.24.0.tar.gz" +url="https://ci-mirrors.rust-lang.org/rustc/crosstool-ng-1.24.0.tar.gz" curl -Lf $url | tar xzf - cd crosstool-ng-crosstool-ng-1.24.0 ./bootstrap diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index b087ea7899..ad675830b7 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -69,7 +69,7 @@ RUN ./build-python.sh # Now build LLVM+Clang 7, afterwards configuring further compilations to use the # clang/clang++ compilers. -COPY dist-x86_64-linux/build-clang.sh /tmp/ +COPY dist-x86_64-linux/build-clang.sh dist-x86_64-linux/llvm-project-centos.patch /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 816bdb34a7..6bbf092878 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -135,6 +135,9 @@ ENV TARGETS=$TARGETS,armv7r-none-eabi ENV TARGETS=$TARGETS,armv7r-none-eabihf ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf +# riscv targets currently do not need a C compiler, as compiler_builtins +# doesn't currently have it enabled, and the riscv gcc compiler is not +# installed. ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ CC_mips64el_unknown_linux_muslabi64=mips64el-linux-gnuabi64-gcc \ @@ -143,7 +146,12 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \ - CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ + CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ \ + CC_riscv32i_unknown_none_elf=false \ + CC_riscv32imc_unknown_none_elf=false \ + CC_riscv32imac_unknown_none_elf=false \ + CC_riscv64imac_unknown_none_elf=false \ + CC_riscv64gc_unknown_none_elf=false ENV RUST_CONFIGURE_ARGS \ --musl-root-armv5te=/musl-armv5te \ diff --git a/src/ci/docker/dist-various-1/install-mips-musl.sh b/src/ci/docker/dist-various-1/install-mips-musl.sh index 29cfb5d960..9584258d23 100755 --- a/src/ci/docker/dist-various-1/install-mips-musl.sh +++ b/src/ci/docker/dist-various-1/install-mips-musl.sh @@ -5,7 +5,7 @@ mkdir /usr/local/mips-linux-musl # originally from # https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/ # OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2 -URL="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc" +URL="https://ci-mirrors.rust-lang.org/rustc" FILE="OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2" curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mips-linux-musl --strip-components=2 diff --git a/src/ci/docker/dist-various-1/install-mipsel-musl.sh b/src/ci/docker/dist-various-1/install-mipsel-musl.sh index de8c359d16..50a8e554b1 100755 --- a/src/ci/docker/dist-various-1/install-mipsel-musl.sh +++ b/src/ci/docker/dist-various-1/install-mipsel-musl.sh @@ -5,7 +5,7 @@ mkdir /usr/local/mipsel-linux-musl # Note that this originally came from: # https://downloads.openwrt.org/snapshots/trunk/malta/generic/ # OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2 -URL="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc" +URL="https://ci-mirrors.rust-lang.org/rustc" FILE="OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2" curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mipsel-linux-musl --strip-components=2 diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh index f04ee78157..925d5ca022 100755 --- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh @@ -4,17 +4,17 @@ set -ex -# Originally from https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz -curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \ +# Originally from https://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz +curl https://ci-mirrors.rust-lang.org/rustc/clang%2Bllvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \ tar xJf - -export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH +export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH -git clone https://github.com/CraneStation/wasi-sysroot +git clone https://github.com/CraneStation/wasi-libc -cd wasi-sysroot -git reset --hard e5f14be38362f1ab83302895a6e74b2ffd0e2302 +cd wasi-libc +git reset --hard f645f498dfbbbc00a7a97874d33082d3605c3f21 make -j$(nproc) INSTALL_DIR=/wasm32-wasi install cd .. -rm -rf reference-sysroot-wasi +rm -rf wasi-libc rm -rf clang+llvm* diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index a1a778c2b2..2f2a10a0e9 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -69,7 +69,7 @@ RUN ./build-python.sh # Now build LLVM+Clang 7, afterwards configuring further compilations to use the # clang/clang++ compilers. -COPY dist-x86_64-linux/build-clang.sh /tmp/ +COPY dist-x86_64-linux/build-clang.sh dist-x86_64-linux/llvm-project-centos.patch /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ diff --git a/src/ci/docker/dist-x86_64-linux/build-clang.sh b/src/ci/docker/dist-x86_64-linux/build-clang.sh index ac681b7168..518f6ef9b7 100755 --- a/src/ci/docker/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/dist-x86_64-linux/build-clang.sh @@ -4,7 +4,7 @@ set -ex source shared.sh -LLVM=llvmorg-8.0.0-rc2 +LLVM=llvmorg-9.0.0 mkdir llvm-project cd llvm-project @@ -12,6 +12,9 @@ cd llvm-project curl -L https://github.com/llvm/llvm-project/archive/$LLVM.tar.gz | \ tar xzf - --strip-components=1 +yum install -y patch +patch -Np1 < ../llvm-project-centos.patch + mkdir clang-build cd clang-build diff --git a/src/ci/docker/dist-x86_64-linux/build-curl.sh b/src/ci/docker/dist-x86_64-linux/build-curl.sh index 8200bbe2fd..0c7eb5fdac 100755 --- a/src/ci/docker/dist-x86_64-linux/build-curl.sh +++ b/src/ci/docker/dist-x86_64-linux/build-curl.sh @@ -5,6 +5,9 @@ source shared.sh VERSION=7.66.0 +# This needs to be downloaded directly from S3, it can't go through the CDN. +# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1 +# (without paying an absurd amount of money). curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/curl-$VERSION.tar.xz \ | xz --decompress \ | tar xf - diff --git a/src/ci/docker/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/dist-x86_64-linux/build-openssl.sh index be8a6c9394..d8f6bdb51b 100755 --- a/src/ci/docker/dist-x86_64-linux/build-openssl.sh +++ b/src/ci/docker/dist-x86_64-linux/build-openssl.sh @@ -4,6 +4,10 @@ set -ex source shared.sh VERSION=1.0.2k + +# This needs to be downloaded directly from S3, it can't go through the CDN. +# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1 +# (without paying an absurd amount of money). URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz curl $URL | tar xzf - diff --git a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh index 797f674b95..f8697c698b 100755 --- a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -25,7 +25,7 @@ cd netbsd mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot -URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc +URL=https://ci-mirrors.rust-lang.org/rustc # Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz curl $URL/2018-03-01-netbsd-src.tgz | tar xzf - diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile index 24e2dea4ca..b2d96aed2a 100644 --- a/src/ci/docker/mingw-check/Dockerfile +++ b/src/ci/docker/mingw-check/Dockerfile @@ -19,7 +19,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +COPY mingw-check/validate-toolstate.sh /scripts/ + ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python2.7 ../x.py build --stage 0 src/tools/build-manifest && \ - python2.7 ../x.py test --stage 0 src/tools/compiletest + python2.7 ../x.py test --stage 0 src/tools/compiletest && \ + /scripts/validate-toolstate.sh diff --git a/src/ci/docker/mingw-check/validate-toolstate.sh b/src/ci/docker/mingw-check/validate-toolstate.sh new file mode 100755 index 0000000000..2ebf1d6d5a --- /dev/null +++ b/src/ci/docker/mingw-check/validate-toolstate.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# A quick smoke test to make sure publish_tooolstate.py works. + +set -euo pipefail +IFS=$'\n\t' + +rm -rf rust-toolstate +git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git +cd rust-toolstate +python2.7 "../../src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" \ + "$(git log --format=%s -n1 HEAD)" "" "" +# Only check maintainers if this build is supposed to publish toolstate. +# Builds that are not supposed to publish don't have the access token. +if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then + TOOLSTATE_VALIDATE_MAINTAINERS_REPO=rust-lang/rust python2.7 \ + "../../src/tools/publish_toolstate.py" +fi +cd .. +rm -rf rust-toolstate diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index cdafcbadc9..f29f9f3bf1 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -172,6 +172,8 @@ docker \ --env CI \ --env TF_BUILD \ --env BUILD_SOURCEBRANCHNAME \ + --env GITHUB_ACTIONS \ + --env GITHUB_REF \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ --env TOOLSTATE_REPO \ --env TOOLSTATE_PUBLISH \ diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index 70155e770a..5670e10be2 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -59,7 +59,7 @@ done # Originally downloaded from: # https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz -URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz +URL=https://ci-mirrors.rust-lang.org/rustc/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}" # Fix up absolute symlinks from the system image. This can be removed diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index efeb0ed0d7..552afbfee7 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -1,6 +1,6 @@ set -ex curl -fo /usr/local/bin/sccache \ - https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl + https://ci-mirrors.rust-lang.org/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl chmod +x /usr/local/bin/sccache diff --git a/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile similarity index 90% rename from src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile rename to src/ci/docker/x86_64-gnu-llvm-7/Dockerfile index 6dbbb22034..a1c9c13fc4 100644 --- a/src/ci/docker/x86_64-gnu-llvm-6.0/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ @@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - llvm-6.0-tools \ + llvm-7-tools \ libedit-dev \ libssl-dev \ pkg-config \ @@ -24,7 +24,7 @@ RUN sh /scripts/sccache.sh # using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-6.0 \ + --llvm-root=/usr/lib/llvm-7 \ --enable-llvm-link-shared ENV SCRIPT python2.7 ../x.py test src/tools/tidy && python2.7 ../x.py test diff --git a/src/ci/docker/x86_64-gnu-tools/Dockerfile b/src/ci/docker/x86_64-gnu-tools/Dockerfile index 7687a6ca23..51193402ee 100644 --- a/src/ci/docker/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/x86_64-gnu-tools/Dockerfile @@ -17,9 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -COPY x86_64-gnu-tools/checkregression.py /tmp/ COPY x86_64-gnu-tools/checktools.sh /tmp/ -COPY x86_64-gnu-tools/repo.sh /tmp/ # Run rustbook with `linkcheck` feature enabled ENV CHECK_LINKS 1 @@ -27,4 +25,4 @@ ENV CHECK_LINKS 1 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --save-toolstates=/tmp/toolstate/toolstates.json -ENV SCRIPT /tmp/checktools.sh ../x.py /tmp/toolstate/toolstates.json linux +ENV SCRIPT /tmp/checktools.sh ../x.py diff --git a/src/ci/docker/x86_64-gnu-tools/checkregression.py b/src/ci/docker/x86_64-gnu-tools/checkregression.py deleted file mode 100755 index 4fbb8c4d20..0000000000 --- a/src/ci/docker/x86_64-gnu-tools/checkregression.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -## This script has two purposes: detect any tool that *regressed*, which is used -## during the week before the beta branches to reject PRs; and detect any tool -## that *changed* to see if we need to update the toolstate repo. - -import sys -import json - -# Regressions for these tools during the beta cutoff week do not cause failure. -# See `status_check` in `checktools.sh` for tools that have to pass on the -# beta/stable branches. -REGRESSION_OK = ["rustc-guide", "miri", "embedded-book"] - -if __name__ == '__main__': - os_name = sys.argv[1] - toolstate_file = sys.argv[2] - current_state = sys.argv[3] - verb = sys.argv[4] # 'regressed' or 'changed' - - with open(toolstate_file, 'r') as f: - toolstate = json.load(f) - with open(current_state, 'r') as f: - current = json.load(f) - - regressed = False - for cur in current: - tool = cur['tool'] - state = cur[os_name] - new_state = toolstate.get(tool, '') - if verb == 'regressed': - updated = new_state < state - elif verb == 'changed': - updated = new_state != state - else: - print('Unknown verb {}'.format(updated)) - sys.exit(2) - if updated: - print( - 'The state of "{}" has {} from "{}" to "{}"' - .format(tool, verb, state, new_state) - ) - if not (verb == 'regressed' and tool in REGRESSION_OK): - regressed = True - - if regressed: - sys.exit(1) diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index ebb8c0bda5..e57fe22713 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -3,18 +3,6 @@ set -eu X_PY="$1" -TOOLSTATE_FILE="$(realpath -m $2)" -OS="$3" -COMMIT="$(git rev-parse HEAD)" -CHANGED_FILES="$(git diff --name-status HEAD HEAD^)" -SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))" -# ^ Number of days after the last promotion of beta. -# Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens. -# The Wednesday after this has value 0. -# We track this value to prevent regressing tools in the last week of the 6-week cycle. - -mkdir -p "$(dirname $TOOLSTATE_FILE)" -touch "$TOOLSTATE_FILE" # Try to test all the tools and store the build/test success in the TOOLSTATE_FILE @@ -34,106 +22,4 @@ python2.7 "$X_PY" test --no-fail-fast \ set -e -cat "$TOOLSTATE_FILE" -echo - -# This function checks if a particular tool is *not* in status "test-pass". -check_tool_failed() { - grep -vq '"'"$1"'":"test-pass"' "$TOOLSTATE_FILE" -} - -# This function checks that if a tool's submodule changed, the tool's state must improve -verify_submodule_changed() { - echo "Verifying status of $1..." - if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then - echo "This PR updated '$2', verifying if status is 'test-pass'..." - if check_tool_failed "$1"; then - echo - echo "⚠️ We detected that this PR updated '$1', but its tests failed." - echo - echo "If you do intend to update '$1', please check the error messages above and" - echo "commit another update." - echo - echo "If you do NOT intend to update '$1', please ensure you did not accidentally" - echo "change the submodule at '$2'. You may ask your reviewer for the" - echo "proper steps." - exit 3 - fi - fi -} - -# deduplicates the submodule check and the assertion that on beta some tools MUST be passing. -# $1 should be "submodule_changed" to only check tools that got changed by this PR, -# or "beta_required" to check all tools that have $2 set to "beta". -check_dispatch() { - if [ "$1" = submodule_changed ]; then - # ignore $2 (branch id) - verify_submodule_changed $3 $4 - elif [ "$2" = beta ]; then - echo "Requiring test passing for $3..." - if check_tool_failed "$3"; then - exit 4 - fi - fi -} - -# List all tools here. -# This function gets called with "submodule_changed" for each PR that changed a submodule, -# and with "beta_required" for each PR that lands on beta/stable. -# The purpose of this function is to *reject* PRs if a tool is not "test-pass" and -# (a) the tool's submodule has been updated, or (b) we landed on beta/stable and the -# tool has to "test-pass" on that branch. -status_check() { - check_dispatch $1 beta book src/doc/book - check_dispatch $1 beta nomicon src/doc/nomicon - check_dispatch $1 beta reference src/doc/reference - check_dispatch $1 beta rust-by-example src/doc/rust-by-example - check_dispatch $1 beta edition-guide src/doc/edition-guide - check_dispatch $1 beta rls src/tools/rls - check_dispatch $1 beta rustfmt src/tools/rustfmt - check_dispatch $1 beta clippy-driver src/tools/clippy - # These tools are not required on the beta/stable branches, but they *do* cause - # PRs to fail if a submodule update does not fix them. - # They will still cause failure during the beta cutoff week, unless `checkregression.py` - # exempts them from that. - check_dispatch $1 nightly miri src/tools/miri - check_dispatch $1 nightly embedded-book src/doc/embedded-book - check_dispatch $1 nightly rustc-guide src/doc/rustc-guide -} - -# If this PR is intended to update one of these tools, do not let the build pass -# when they do not test-pass. - -status_check "submodule_changed" - -CHECK_NOT="$(readlink -f "$(dirname $0)/checkregression.py")" -# This callback is called by `commit_toolstate_change`, see `repo.sh`. -change_toolstate() { - # only update the history - if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then - echo 'Toolstate is not changed. Not updating.' - else - if [ $SIX_WEEK_CYCLE -ge 35 ]; then - # Reject any regressions during the week before beta cutoff. - python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed - fi - sed -i "1 a\\ -$COMMIT\t$(cat "$TOOLSTATE_FILE") -" "history/$OS.tsv" - fi -} - -if [ "$RUST_RELEASE_CHANNEL" = nightly ]; then - if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then - . "$(dirname $0)/repo.sh" - MESSAGE_FILE=$(mktemp -t msg.XXXXXX) - echo "($OS CI update)" > "$MESSAGE_FILE" - commit_toolstate_change "$MESSAGE_FILE" change_toolstate - rm -f "$MESSAGE_FILE" - fi - exit 0 -fi - -# abort compilation if an important tool doesn't build -# (this code is reachable if not on the nightly channel) -status_check "beta_required" +python2.7 "$X_PY" test check-tools diff --git a/src/ci/docker/x86_64-gnu-tools/repo.sh b/src/ci/docker/x86_64-gnu-tools/repo.sh deleted file mode 100644 index 82700a00fb..0000000000 --- a/src/ci/docker/x86_64-gnu-tools/repo.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh - -# This file provides the function `commit_toolstate_change` for pushing a change -# to the `rust-toolstate` repository. -# -# The function relies on a GitHub bot user, which should have a Personal access -# token defined in the environment variable $TOOLSTATE_REPO_ACCESS_TOKEN. If for -# some reason you need to change the token, please update the Azure Pipelines -# variable group. -# -# 1. Generate a new Personal access token: -# -# * Login to the bot account, and go to Settings -> Developer settings -> -# Personal access tokens -# * Click "Generate new token" -# * Enable the "public_repo" permission, then click "Generate token" -# * Copy the generated token (should be a 40-digit hexadecimal number). -# Save it somewhere secure, as the token would be gone once you leave -# the page. -# -# 2. Update the variable group in Azure Pipelines -# -# * Ping a member of the infrastructure team to do this. -# -# 4. Replace the email address below if the bot account identity is changed -# -# * See -# if a private email by GitHub is wanted. - -commit_toolstate_change() { - OLDFLAGS="$-" - set -eu - - git config --global user.email '7378925+rust-toolstate-update@users.noreply.github.com' - git config --global user.name 'Rust Toolstate Update' - git config --global credential.helper store - printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \ - > "$HOME/.git-credentials" - git clone --depth=1 $TOOLSTATE_REPO - - cd rust-toolstate - FAILURE=1 - MESSAGE_FILE="$1" - shift - for RETRY_COUNT in 1 2 3 4 5; do - # Call the callback. - # - If we are in the `auto` branch (pre-landing), this is called from `checktools.sh` and - # the callback is `change_toolstate` in that file. The purpose of this is to publish the - # test results (the new commit-to-toolstate mapping) in the toolstate repo. - # - If we are in the `master` branch (post-landing), this is called by the CI pipeline - # and the callback is `src/tools/publish_toolstate.py`. The purpose is to publish - # the new "current" toolstate in the toolstate repo. - "$@" - # `git commit` failing means nothing to commit. - FAILURE=0 - git commit -a -F "$MESSAGE_FILE" || break - # On failure randomly sleep for 0 to 3 seconds as a crude way to introduce jittering. - git push origin master && break || sleep $(LC_ALL=C tr -cd 0-3 < /dev/urandom | head -c 1) - FAILURE=1 - git fetch origin master - git reset --hard origin/master - done - cd .. - - set +eu - set "-$OLDFLAGS" - return $FAILURE -} diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh new file mode 100755 index 0000000000..d8ff740782 --- /dev/null +++ b/src/ci/publish_toolstate.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +set -eu + +# The following lines are also found in src/bootstrap/toolstate.rs, +# so if updating here, please also update that file. + +export MESSAGE_FILE=$(mktemp -t msg.XXXXXX) + +git config --global user.email '7378925+rust-toolstate-update@users.noreply.github.com' +git config --global user.name 'Rust Toolstate Update' +git config --global credential.helper store +printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \ + > "$HOME/.git-credentials" +git clone --depth=1 $TOOLSTATE_REPO + +cd rust-toolstate +FAILURE=1 +for RETRY_COUNT in 1 2 3 4 5; do + # The purpose is to publish the new "current" toolstate in the toolstate repo. + "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" \ + "$(git log --format=%s -n1 HEAD)" \ + "$MESSAGE_FILE" \ + "$TOOLSTATE_REPO_ACCESS_TOKEN" + # `git commit` failing means nothing to commit. + FAILURE=0 + git commit -a -F "$MESSAGE_FILE" || break + # On failure randomly sleep for 0 to 3 seconds as a crude way to introduce jittering. + git push origin master && break || sleep $(LC_ALL=C tr -cd 0-3 < /dev/urandom | head -c 1) + FAILURE=1 + git fetch origin master + git reset --hard origin/master +done diff --git a/src/ci/run.sh b/src/ci/run.sh index 7c5df63ec0..5bbe21051b 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -23,9 +23,7 @@ fi ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh" -branch_name=$(getCIBranch) - -if [ ! isCI ] || [ "$branch_name" = "auto" ] || [ "$branch_name" = "try" ]; then +if ! isCI || isCiBranch auto || isCiBranch beta; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" fi diff --git a/src/ci/scripts/clean-disk.sh b/src/ci/scripts/clean-disk.sh new file mode 100755 index 0000000000..c50de37c49 --- /dev/null +++ b/src/ci/scripts/clean-disk.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# This script deletes some of the Azure-provided artifacts. We don't use these, +# and disk space is at a premium on our builders. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +# All the Linux builds happen inside Docker. +if isLinux; then + # 6.7GB + sudo rm -rf /opt/ghc + # 16GB + sudo rm -rf /usr/share/dotnet +fi diff --git a/src/ci/scripts/collect-cpu-stats.sh b/src/ci/scripts/collect-cpu-stats.sh new file mode 100755 index 0000000000..08065431f9 --- /dev/null +++ b/src/ci/scripts/collect-cpu-stats.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Spawn a background process to collect CPU usage statistics which we'll upload +# at the end of the build. See the comments in the script here for more +# information. + +set -euo pipefail +IFS=$'\n\t' + +python src/ci/cpu-usage-over-time.py &> cpu-usage.csv & diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index e9b685718e..f0179994e8 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -9,15 +9,15 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" if isMacOS; then - curl -f "${MIRRORS_BASE}/clang%2Bllvm-7.0.0-x86_64-apple-darwin.tar.xz" | tar xJf - + curl -f "${MIRRORS_BASE}/clang%2Bllvm-9.0.0-x86_64-darwin-apple.tar.xz" | tar xJf - - ciCommandSetEnv CC "$(pwd)/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang" - ciCommandSetEnv CXX "$(pwd)/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++" + ciCommandSetEnv CC "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang" + ciCommandSetEnv CXX "$(pwd)/clang+llvm-9.0.0-x86_64-darwin-apple/bin/clang++" # Configure `AR` specifically so rustbuild doesn't try to infer it as # `clang-ar` by accident. ciCommandSetEnv AR "ar" -elif isWindows && [[ -z ${MINGW_URL+x} ]]; then +elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then # If we're compiling for MSVC then we, like most other distribution builders, # switch to clang as the compiler. This'll allow us eventually to enable LTO # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think @@ -27,17 +27,18 @@ elif isWindows && [[ -z ${MINGW_URL+x} ]]; then # Note that the LLVM installer is an NSIS installer # # Original downloaded here came from - # http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe - # That installer was run through `wine` on Linux and then the resulting - # installation directory (found in `$HOME/.wine/drive_c/Program Files/LLVM`) was - # packaged up into a tarball. We've had issues otherwise that the installer will - # randomly hang, provide not a lot of useful information, pollute global state, - # etc. In general the tarball is just more confined and easier to deal with when - # working with various CI environments. + # http://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe + # That installer was run through `wine ./installer.exe /S /NCRC` on Linux + # and then the resulting installation directory (found in + # `$HOME/.wine/drive_c/Program Files/LLVM`) was packaged up into a tarball. + # We've had issues otherwise that the installer will randomly hang, provide + # not a lot of useful information, pollute global state, etc. In general the + # tarball is just more confined and easier to deal with when working with + # various CI environments. mkdir -p citools cd citools - curl -f "${MIRRORS_BASE}/LLVM-7.0.0-win64.tar.gz" | tar xzf - + curl -f "${MIRRORS_BASE}/LLVM-9.0.0-win64.tar.gz" | tar xzf - ciCommandSetEnv RUST_CONFIGURE_ARGS \ "${RUST_CONFIGURE_ARGS} --set llvm.clang-cl=$(pwd)/clang-rust/bin/clang-cl.exe" fi diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh index b4e8b889f5..98373df7fc 100755 --- a/src/ci/scripts/install-mingw.sh +++ b/src/ci/scripts/install-mingw.sh @@ -27,19 +27,38 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" +MINGW_ARCHIVE_32="i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z" +MINGW_ARCHIVE_64="x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z" + if isWindows; then - if [[ -z "${MINGW_URL+x}" ]]; then - arch=i686 - if [ "$MSYS_BITS" = "64" ]; then - arch=x86_64 - fi + case "${CI_JOB_NAME}" in + *i686*) + bits=32 + arch=i686 + mingw_archive="${MINGW_ARCHIVE_32}" + ;; + *x86_64*) + bits=64 + arch=x86_64 + mingw_archive="${MINGW_ARCHIVE_64}" + ;; + *) + echo "src/ci/scripts/install-mingw.sh can't detect the builder's architecture" + echo "please tweak it to recognize the builder named '${CI_JOB_NAME}'" + exit 1 + ;; + esac + + if [[ "${CUSTOM_MINGW-0}" -ne 1 ]]; then pacman -S --noconfirm --needed mingw-w64-$arch-toolchain mingw-w64-$arch-cmake \ mingw-w64-$arch-gcc mingw-w64-$arch-python2 - ciCommandAddPath "${SYSTEM_WORKFOLDER}/msys2/mingw${MSYS_BITS}/bin" + ciCommandAddPath "$(ciCheckoutPath)/msys2/mingw${bits}/bin" else - curl -o mingw.7z "${MINGW_URL}/${MINGW_ARCHIVE}" + mingw_dir="mingw${bits}" + + curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}" 7z x -y mingw.7z > /dev/null - curl -o "${MINGW_DIR}/bin/gdborig.exe" "${MINGW_URL}/2017-04-20-${MSYS_BITS}bit-gdborig.exe" - ciCommandAddPath "$(pwd)/${MINGW_DIR}/bin" + curl -o "${mingw_dir}/bin/gdborig.exe" "${MIRRORS_BASE}/2017-04-20-${bits}bit-gdborig.exe" + ciCommandAddPath "$(pwd)/${mingw_dir}/bin" fi fi diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh index ce37c3b146..c9fafc7fe6 100755 --- a/src/ci/scripts/install-msys2.sh +++ b/src/ci/scripts/install-msys2.sh @@ -12,8 +12,8 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" if isWindows; then - choco install msys2 --params="/InstallDir:${SYSTEM_WORKFOLDER}/msys2 /NoPath" -y --no-progress - mkdir -p "${SYSTEM_WORKFOLDER}/msys2/home/${USERNAME}" + choco install msys2 --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress + mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}" - ciCommandAddPath "${SYSTEM_WORKFOLDER}/msys2/usr/bin" + ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin" fi diff --git a/src/ci/scripts/run-build-from-ci.sh b/src/ci/scripts/run-build-from-ci.sh new file mode 100755 index 0000000000..c02117f459 --- /dev/null +++ b/src/ci/scripts/run-build-from-ci.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Start the CI build. You shouldn't run this locally: call either src/ci/run.sh +# or src/ci/docker/run.sh instead. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +export CI="true" +export SRC=. + +# Remove any preexisting rustup installation since it can interfere +# with the cargotest step and its auto-detection of things like Clippy in +# the environment +rustup self uninstall -y || true +if [ -z "${IMAGE+x}" ]; then + src/ci/run.sh +else + src/ci/docker/run.sh "${IMAGE}" +fi diff --git a/src/ci/scripts/setup-environment.sh b/src/ci/scripts/setup-environment.sh new file mode 100755 index 0000000000..e126a06eda --- /dev/null +++ b/src/ci/scripts/setup-environment.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# This script guesses some environment variables based on the builder name and +# the current platform, to reduce the amount of variables defined in the CI +# configuration. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +# Builders starting with `dist-` are dist builders, but if they also end with +# `-alt` they are alternate dist builders. +if [[ "${CI_JOB_NAME}" = dist-* ]]; then + if [[ "${CI_JOB_NAME}" = *-alt ]]; then + echo "alternate dist builder detected, setting DEPLOY_ALT=1" + ciCommandSetEnv DEPLOY_ALT 1 + else + echo "normal dist builder detected, setting DEPLOY=1" + ciCommandSetEnv DEPLOY 1 + fi +fi + +# All the Linux builds happen inside Docker. +if isLinux; then + if [[ -z "${IMAGE+x}" ]]; then + echo "linux builder detected, using docker to run the build" + ciCommandSetEnv IMAGE "${CI_JOB_NAME}" + else + echo "a custom docker image is already set" + fi +fi diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 718a5379ae..98120f5dff 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -4,7 +4,7 @@ # `source shared.sh`, hence the invalid shebang and not being # marked as an executable file in git. -export MIRRORS_BASE="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc" +export MIRRORS_BASE="https://ci-mirrors.rust-lang.org/rustc" # See http://unix.stackexchange.com/questions/82598 # Duplicated in docker/dist-various-2/shared.sh @@ -27,27 +27,66 @@ function retry { } function isCI { - [ "$CI" = "true" ] || [ "$TF_BUILD" = "True" ] + [[ "${CI-false}" = "true" ]] || isAzurePipelines || isGitHubActions +} + +function isAzurePipelines { + [[ "${TF_BUILD-False}" = "True" ]] +} + +function isGitHubActions { + [[ "${GITHUB_ACTIONS-false}" = "true" ]] } function isMacOS { - [ "$AGENT_OS" = "Darwin" ] + [[ "${OSTYPE}" = "darwin"* ]] } function isWindows { - [ "$AGENT_OS" = "Windows_NT" ] + [[ "${OSTYPE}" = "cygwin" ]] || [[ "${OSTYPE}" = "msys" ]] } function isLinux { - [ "$AGENT_OS" = "Linux" ] + [[ "${OSTYPE}" = "linux-gnu" ]] } -function getCIBranch { - echo "$BUILD_SOURCEBRANCHNAME" +function isCiBranch { + if [[ $# -ne 1 ]]; then + echo "usage: $0 " + exit 1 + fi + name="$1" + + if isAzurePipelines; then + [[ "${BUILD_SOURCEBRANCHNAME}" = "${name}" ]] + elif isGitHubActions; then + [[ "${GITHUB_REF}" = "refs/heads/${name}" ]] + else + echo "isCiBranch only works inside CI!" + exit 1 + fi } function ciCommit { - echo "${BUILD_SOURCEVERSION}" + if isAzurePipelines; then + echo "${BUILD_SOURCEVERSION}" + elif isGitHubActions; then + echo "${GITHUB_SHA}" + else + echo "ciCommit only works inside CI!" + exit 1 + fi +} + +function ciCheckoutPath { + if isAzurePipelines; then + echo "${SYSTEM_WORKFOLDER}" + elif isGitHubActions; then + echo "${GITHUB_WORKSPACE}" + else + echo "ciCheckoutPath only works inside CI!" + exit 1 + fi } function ciCommandAddPath { @@ -57,7 +96,14 @@ function ciCommandAddPath { fi path="$1" - echo "##vso[task.prependpath]${path}" + if isAzurePipelines; then + echo "##vso[task.prependpath]${path}" + elif isGitHubActions; then + echo "::add-path::${value}" + else + echo "ciCommandAddPath only works inside CI!" + exit 1 + fi } function ciCommandSetEnv { @@ -68,5 +114,12 @@ function ciCommandSetEnv { name="$1" value="$2" - echo "##vso[task.setvariable variable=${name}]${value}" + if isAzurePipelines; then + echo "##vso[task.setvariable variable=${name}]${value}" + elif isGitHubActions; then + echo "::set-env name=${name}::${value}" + else + echo "ciCommandSetEnv only works inside CI!" + exit 1 + fi } diff --git a/src/doc/book/ci/dictionary.txt b/src/doc/book/ci/dictionary.txt index 05f61c0a22..98f4b89e36 100644 --- a/src/doc/book/ci/dictionary.txt +++ b/src/doc/book/ci/dictionary.txt @@ -160,7 +160,6 @@ Filesystem filesystem's filesystems Firefox -FnBox FnMut FnOnce formatter diff --git a/src/doc/book/src/ch04-03-slices.md b/src/doc/book/src/ch04-03-slices.md index 8ad29a896c..969884cf47 100644 --- a/src/doc/book/src/ch04-03-slices.md +++ b/src/doc/book/src/ch04-03-slices.md @@ -158,7 +158,7 @@ in the slice and `ending_index` is one more than the last position in the slice. Internally, the slice data structure stores the starting position and the length of the slice, which corresponds to `ending_index` minus `starting_index`. So in the case of `let world = &s[6..11];`, `world` would be -a slice that contains a pointer to the 7th byte of `s` with a length value of 5. +a slice that contains a pointer to the 7th byte (counting from 1) of `s` with a length value of 5. Figure 4-6 shows this in a diagram. diff --git a/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md index f6a9b15703..d2674f3f19 100644 --- a/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md +++ b/src/doc/book/src/ch07-02-defining-modules-to-control-scope-and-privacy.md @@ -29,7 +29,7 @@ Listing 7-1 into *src/lib.rs* to define some modules and function signatures. Filename: src/lib.rs -```rust +```rust,ignore mod front_of_house { mod hosting { fn add_to_waitlist() {} diff --git a/src/doc/book/src/ch10-00-generics.md b/src/doc/book/src/ch10-00-generics.md index a928b81e7c..b411210be2 100644 --- a/src/doc/book/src/ch10-00-generics.md +++ b/src/doc/book/src/ch10-00-generics.md @@ -125,7 +125,7 @@ number in two different lists. fn largest(list: &[i32]) -> i32 { let mut largest = list[0]; - for &item in list.iter() { + for &item in list { if item > largest { largest = item; } diff --git a/src/doc/book/src/ch16-03-shared-state.md b/src/doc/book/src/ch16-03-shared-state.md index 7050d4db15..c39d302b92 100644 --- a/src/doc/book/src/ch16-03-shared-state.md +++ b/src/doc/book/src/ch16-03-shared-state.md @@ -103,10 +103,9 @@ to change the inner `i32` to 6. Now, let’s try to share a value between multiple threads using `Mutex`. We’ll spin up 10 threads and have them each increment a counter value by 1, so -the counter goes from 0 to 10. Note that the next few examples will have -compiler errors, and we’ll use those errors to learn more about using -`Mutex` and how Rust helps us use it correctly. Listing 16-13 has our -starting example: +the counter goes from 0 to 10. The next example in Listing 16-13 will have +a compiler error, and we’ll use that error to learn more about using +`Mutex` and how Rust helps us use it correctly. Filename: src/main.rs @@ -154,110 +153,23 @@ program. We hinted that this example wouldn’t compile. Now let’s find out why! ```text -error[E0382]: capture of moved value: `counter` - --> src/main.rs:10:27 - | -9 | let handle = thread::spawn(move || { - | ------- value moved (into closure) here -10 | let mut num = counter.lock().unwrap(); - | ^^^^^^^ value captured here after move - | - = note: move occurs because `counter` has type `std::sync::Mutex`, - which does not implement the `Copy` trait - error[E0382]: use of moved value: `counter` - --> src/main.rs:21:29 + --> src/main.rs:9:36 | 9 | let handle = thread::spawn(move || { - | ------- value moved (into closure) here -... -21 | println!("Result: {}", *counter.lock().unwrap()); - | ^^^^^^^ value used here after move - | - = note: move occurs because `counter` has type `std::sync::Mutex`, - which does not implement the `Copy` trait - -error: aborting due to 2 previous errors -``` - -The error message states that the `counter` value is moved into the closure and -then captured when we call `lock`. That description sounds like what we wanted, -but it’s not allowed! - -Let’s figure this out by simplifying the program. Instead of making 10 threads -in a `for` loop, let’s just make two threads without a loop and see what -happens. Replace the first `for` loop in Listing 16-13 with this code instead: - -```rust,ignore,does_not_compile -use std::sync::Mutex; -use std::thread; - -fn main() { - let counter = Mutex::new(0); - let mut handles = vec![]; - - let handle = thread::spawn(move || { - let mut num = counter.lock().unwrap(); - - *num += 1; - }); - handles.push(handle); - - let handle2 = thread::spawn(move || { - let mut num2 = counter.lock().unwrap(); - - *num2 += 1; - }); - handles.push(handle2); - - for handle in handles { - handle.join().unwrap(); - } - - println!("Result: {}", *counter.lock().unwrap()); -} -``` - -We make two threads and change the variable names used with the second thread -to `handle2` and `num2`. When we run the code this time, compiling gives us the -following: - -```text -error[E0382]: capture of moved value: `counter` - --> src/main.rs:16:24 - | -8 | let handle = thread::spawn(move || { - | ------- value moved (into closure) here -... -16 | let mut num2 = counter.lock().unwrap(); - | ^^^^^^^ value captured here after move - | - = note: move occurs because `counter` has type `std::sync::Mutex`, - which does not implement the `Copy` trait - -error[E0382]: use of moved value: `counter` - --> src/main.rs:26:29 - | -8 | let handle = thread::spawn(move || { - | ------- value moved (into closure) here -... -26 | println!("Result: {}", *counter.lock().unwrap()); - | ^^^^^^^ value used here after move + | ^^^^^^^ value moved into closure here, +in previous iteration of loop +10 | let mut num = counter.lock().unwrap(); + | ------- use occurs due to use in closure | = note: move occurs because `counter` has type `std::sync::Mutex`, - which does not implement the `Copy` trait - -error: aborting due to 2 previous errors +which does not implement the `Copy` trait ``` -Aha! The first error message indicates that `counter` is moved into the closure -for the thread associated with `handle`. That move is preventing us from -capturing `counter` when we try to call `lock` on it and store the result in -`num2` in the second thread! So Rust is telling us that we can’t move ownership -of `counter` into multiple threads. This was hard to see earlier because our -threads were in a loop, and Rust can’t point to different threads in different -iterations of the loop. Let’s fix the compiler error with a multiple-ownership -method we discussed in Chapter 15. +The error message states that the `counter` value was moved in the previous +iteration of the loop. So Rust is telling us that we can’t move the ownership +of lock `counter` into multiple threads. Let’s fix the compiler error with a +multiple-ownership method we discussed in Chapter 15. #### Multiple Ownership with Multiple Threads @@ -304,30 +216,27 @@ Once again, we compile and get... different errors! The compiler is teaching us a lot. ```text -error[E0277]: the trait bound `std::rc::Rc>: -std::marker::Send` is not satisfied in `[closure@src/main.rs:11:36: -15:10 counter:std::rc::Rc>]` +error[E0277]: `std::rc::Rc>` cannot be sent between threads safely --> src/main.rs:11:22 | 11 | let handle = thread::spawn(move || { | ^^^^^^^^^^^^^ `std::rc::Rc>` cannot be sent between threads safely | - = help: within `[closure@src/main.rs:11:36: 15:10 -counter:std::rc::Rc>]`, the trait `std::marker::Send` is -not implemented for `std::rc::Rc>` + = help: within `[closure@src/main.rs:11:36: 14:10 +counter:std::rc::Rc>]`, the trait `std::marker::Send` +is not implemented for `std::rc::Rc>` = note: required because it appears within the type -`[closure@src/main.rs:11:36: 15:10 counter:std::rc::Rc>]` +`[closure@src/main.rs:11:36: 14:10 counter:std::rc::Rc>]` = note: required by `std::thread::spawn` ``` -Wow, that error message is very wordy! Here are some important parts to focus -on: the first inline error says `` `std::rc::Rc>` cannot -be sent between threads safely ``. The reason for this is in the next important -part to focus on, the error message. The distilled error message says `` the -trait bound `Send` is not satisfied ``. We’ll talk about `Send` in the next -section: it’s one of the traits that ensures the types we use with threads are -meant for use in concurrent situations. +Wow, that error message is very wordy! Here’s the important part to focus +on: `` `Rc>` cannot be sent between threads safely ``. The compiler +is also telling us the reason why: ``the trait `Send` is not implemented for +`Rc>` ``. We’ll talk about `Send` in the next section: it’s one of +the traits that ensures the types we use with threads are meant for use in +concurrent situations. Unfortunately, `Rc` is not safe to share across threads. When `Rc` manages the reference count, it adds to the count for each call to `clone` and diff --git a/src/doc/book/src/ch20-02-multithreaded.md b/src/doc/book/src/ch20-02-multithreaded.md index 1f80bbb208..40d3a172c8 100644 --- a/src/doc/book/src/ch20-02-multithreaded.md +++ b/src/doc/book/src/ch20-02-multithreaded.md @@ -944,7 +944,7 @@ impl Worker { println!("Worker {} got a job; executing.", id); - (*job)(); + job(); } }); @@ -976,109 +976,6 @@ The call to `recv` blocks, so if there is no job yet, the current thread will wait until a job becomes available. The `Mutex` ensures that only one `Worker` thread at a time is trying to request a job. -Theoretically, this code should compile. Unfortunately, the Rust compiler isn’t -perfect yet, and we get this error: - -```text -error[E0161]: cannot move a value of type std::ops::FnOnce() + -std::marker::Send: the size of std::ops::FnOnce() + std::marker::Send cannot be -statically determined - --> src/lib.rs:63:17 - | -63 | (*job)(); - | ^^^^^^ -``` - -This error is fairly cryptic because the problem is fairly cryptic. To call a -`FnOnce` closure that is stored in a `Box` (which is what our `Job` type -alias is), the closure needs to move itself *out* of the `Box` because the -closure takes ownership of `self` when we call it. In general, Rust doesn’t -allow us to move a value out of a `Box` because Rust doesn’t know how big -the value inside the `Box` will be: recall in Chapter 15 that we used -`Box` precisely because we had something of an unknown size that we wanted -to store in a `Box` to get a value of a known size. - -As you saw in Listing 17-15, we can write methods that use the syntax `self: -Box`, which allows the method to take ownership of a `Self` value stored -in a `Box`. That’s exactly what we want to do here, but unfortunately Rust -won’t let us: the part of Rust that implements behavior when a closure is -called isn’t implemented using `self: Box`. So Rust doesn’t yet -understand that it could use `self: Box` in this situation to take -ownership of the closure and move the closure out of the `Box`. - -Rust is still a work in progress with places where the compiler could be -improved, but in the future, the code in Listing 20-20 should work just fine. -People just like you are working to fix this and other issues! After you’ve -finished this book, we would love for you to join in. - -But for now, let’s work around this problem using a handy trick. We can tell -Rust explicitly that in this case we can take ownership of the value inside the -`Box` using `self: Box`; then, once we have ownership of the closure, -we can call it. This involves defining a new trait `FnBox` with the method -`call_box` that will use `self: Box` in its signature, defining `FnBox` -for any type that implements `FnOnce()`, changing our type alias to use the new -trait, and changing `Worker` to use the `call_box` method. These changes are -shown in Listing 20-21. - -Filename: src/lib.rs - -```rust,ignore -trait FnBox { - fn call_box(self: Box); -} - -impl FnBox for F { - fn call_box(self: Box) { - (*self)() - } -} - -type Job = Box; - -// --snip-- - -impl Worker { - fn new(id: usize, receiver: Arc>>) -> Worker { - let thread = thread::spawn(move || { - loop { - let job = receiver.lock().unwrap().recv().unwrap(); - - println!("Worker {} got a job; executing.", id); - - job.call_box(); - } - }); - - Worker { - id, - thread, - } - } -} -``` - -Listing 20-21: Adding a new trait `FnBox` to work around -the current limitations of `Box` - -First, we create a new trait named `FnBox`. This trait has the one method -`call_box`, which is similar to the `call` methods on the other `Fn*` traits -except that it takes `self: Box` to take ownership of `self` and move the -value out of the `Box`. - -Next, we implement the `FnBox` trait for any type `F` that implements the -`FnOnce()` trait. Effectively, this means that any `FnOnce()` closures can use -our `call_box` method. The implementation of `call_box` uses `(*self)()` to -move the closure out of the `Box` and call the closure. - -We now need our `Job` type alias to be a `Box` of anything that implements our -new trait `FnBox`. This will allow us to use `call_box` in `Worker` when we get -a `Job` value instead of invoking the closure directly. Implementing the -`FnBox` trait for any `FnOnce()` closure means we don’t have to change anything -about the actual values we’re sending down the channel. Now Rust is able to -recognize that what we want to do is fine. - -This trick is very sneaky and complicated. Don’t worry if it doesn’t make -perfect sense; someday, it will be completely unnecessary. With the implementation of this trick, our thread pool is in a working state! Give it a `cargo run` and make some requests: @@ -1136,7 +1033,7 @@ thread run them. > limitation is not caused by our web server. After learning about the `while let` loop in Chapter 18, you might be wondering -why we didn’t write the worker thread code as shown in Listing 20-22. +why we didn’t write the worker thread code as shown in Listing 20-21. Filename: src/lib.rs @@ -1149,7 +1046,7 @@ impl Worker { while let Ok(job) = receiver.lock().unwrap().recv() { println!("Worker {} got a job; executing.", id); - job.call_box(); + job(); } }); @@ -1161,7 +1058,7 @@ impl Worker { } ``` -Listing 20-22: An alternative implementation of +Listing 20-21: An alternative implementation of `Worker::new` using `while let` This code compiles and runs but doesn’t result in the desired threading @@ -1175,13 +1072,13 @@ lock. But this implementation can also result in the lock being held longer than intended if we don’t think carefully about the lifetime of the `MutexGuard`. Because the values in the `while` expression remain in scope for the duration of the block, the lock remains held for the duration of the -call to `job.call_box()`, meaning other workers cannot receive jobs. +call to `job()`, meaning other workers cannot receive jobs. By using `loop` instead and acquiring the lock and a job within the block rather than outside it, the `MutexGuard` returned from the `lock` method is dropped as soon as the `let job` statement ends. This ensures that the lock is held during the call to `recv`, but it is released before the call to -`job.call_box()`, allowing multiple requests to be serviced concurrently. +`job()`, allowing multiple requests to be serviced concurrently. [creating-type-synonyms-with-type-aliases]: ch19-04-advanced-types.html#creating-type-synonyms-with-type-aliases diff --git a/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md b/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md index 61e93f1fc5..e255e32a81 100644 --- a/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md +++ b/src/doc/book/src/ch20-03-graceful-shutdown-and-cleanup.md @@ -450,17 +450,7 @@ pub struct ThreadPool { sender: mpsc::Sender, } -trait FnBox { - fn call_box(self: Box); -} - -impl FnBox for F { - fn call_box(self: Box) { - (*self)() - } -} - -type Job = Box; +type Job = Box; impl ThreadPool { /// Create a new ThreadPool. @@ -536,7 +526,7 @@ impl Worker { Message::NewJob(job) => { println!("Worker {} got a job; executing.", id); - job.call_box(); + job(); }, Message::Terminate => { println!("Worker {} was told to terminate.", id); diff --git a/src/doc/edition-guide/.github/workflows/main.yml b/src/doc/edition-guide/.github/workflows/main.yml new file mode 100644 index 0000000000..3f83cb26ed --- /dev/null +++ b/src/doc/edition-guide/.github/workflows/main.yml @@ -0,0 +1,28 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Update rustup + run: rustup self update + - name: Install Rust + run: | + rustup set profile minimal + rustup toolchain install nightly -c rust-docs + rustup default nightly + - name: Install mdbook + run: | + mkdir bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.3.4/mdbook-v0.3.4-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + echo "##[add-path]$(pwd)/bin" + - name: Report versions + run: | + rustup --version + rustc -Vv + mdbook --version + - name: Run tests + run: mdbook test \ No newline at end of file diff --git a/src/doc/edition-guide/.travis.yml b/src/doc/edition-guide/.travis.yml deleted file mode 100644 index bb46f7103b..0000000000 --- a/src/doc/edition-guide/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: rust -cache: cargo -rust: nightly -before_script: - - cargo install mdbook -Z install-upgrade - - mdbook --version -script: - - mdbook build - - mdbook test diff --git a/src/doc/edition-guide/README.md b/src/doc/edition-guide/README.md index f732918256..bd47219a8d 100644 --- a/src/doc/edition-guide/README.md +++ b/src/doc/edition-guide/README.md @@ -1,7 +1,5 @@ # The Rust Edition Guide -[![Build Status](https://api.travis-ci.com/rust-lang-nursery/edition-guide.svg?branch=master)](https://travis-ci.com/rust-lang-nursery/edition-guide) - This book explains the concept of "editions", major new eras in [Rust]'s development. You can [read the book online](https://doc.rust-lang.org/nightly/edition-guide/). diff --git a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-workspaces-for-multi-package-projects.md b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-workspaces-for-multi-package-projects.md index c2189e43d3..9804ac9a90 100644 --- a/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-workspaces-for-multi-package-projects.md +++ b/src/doc/edition-guide/src/rust-2018/cargo-and-crates-io/cargo-workspaces-for-multi-package-projects.md @@ -21,7 +21,7 @@ is a *workspace* that contains many related packages: and more. -[the `futures` package]: https://github.com/rust-lang-nursery/futures-rs +[the `futures` package]: https://github.com/rust-lang/futures-rs Workspaces allow these packages to be developed individually, but they share a single set of dependencies, and therefore have a single target directory diff --git a/src/doc/edition-guide/src/rust-2018/rustup-for-managing-rust-versions.md b/src/doc/edition-guide/src/rust-2018/rustup-for-managing-rust-versions.md index f2b2c81b79..1a2f111268 100644 --- a/src/doc/edition-guide/src/rust-2018/rustup-for-managing-rust-versions.md +++ b/src/doc/edition-guide/src/rust-2018/rustup-for-managing-rust-versions.md @@ -133,7 +133,7 @@ contains a copy of Rust's documentation, so that you can read it offline. This component cannot be removed for now; if that's of interest, please comment on [this -issue](https://github.com/rust-lang-nursery/rustup.rs/issues/998). +issue](https://github.com/rust-lang/rustup.rs/issues/998). ### `rust-src` for a copy of Rust's source code diff --git a/src/doc/nomicon/.github/workflows/main.yml b/src/doc/nomicon/.github/workflows/main.yml new file mode 100644 index 0000000000..3f83cb26ed --- /dev/null +++ b/src/doc/nomicon/.github/workflows/main.yml @@ -0,0 +1,28 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Update rustup + run: rustup self update + - name: Install Rust + run: | + rustup set profile minimal + rustup toolchain install nightly -c rust-docs + rustup default nightly + - name: Install mdbook + run: | + mkdir bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.3.4/mdbook-v0.3.4-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + echo "##[add-path]$(pwd)/bin" + - name: Report versions + run: | + rustup --version + rustc -Vv + mdbook --version + - name: Run tests + run: mdbook test \ No newline at end of file diff --git a/src/doc/nomicon/.travis.yml b/src/doc/nomicon/.travis.yml deleted file mode 100644 index 0e85c20fe2..0000000000 --- a/src/doc/nomicon/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: rust - -cache: cargo - -rust: - - nightly - -before_script: - - (cargo install mdbook --force || true) - -script: - - export PATH=$PATH:/home/travis/.cargo/bin; - - mdbook test - diff --git a/src/doc/nomicon/README.md b/src/doc/nomicon/README.md index 650659e66c..9e511a2b11 100644 --- a/src/doc/nomicon/README.md +++ b/src/doc/nomicon/README.md @@ -23,7 +23,7 @@ infinitesimal fragments of despair. Building the Nomicon requires [mdBook]. To get it: -[mdBook]: https://github.com/rust-lang-nursery/mdBook +[mdBook]: https://github.com/rust-lang/mdBook ```bash $ cargo install mdbook diff --git a/src/doc/nomicon/src/other-reprs.md b/src/doc/nomicon/src/other-reprs.md index ec21932b7d..6212b6cabd 100644 --- a/src/doc/nomicon/src/other-reprs.md +++ b/src/doc/nomicon/src/other-reprs.md @@ -1,7 +1,7 @@ # Alternative representations Rust allows you to specify alternative data layout strategies from the default. -There's also the [reference]. +There's also the [unsafe code guidelines] (note that it's **NOT** normative). @@ -143,7 +143,7 @@ This is a modifier on `repr(C)` and `repr(rust)`. It is incompatible with -[reference]: https://github.com/rust-rfcs/unsafe-code-guidelines/tree/master/reference/src/representation.md +[unsafe code guidelines]: https://rust-lang.github.io/unsafe-code-guidelines/layout.html [drop flags]: drop-flags.html [ub loads]: https://github.com/rust-lang/rust/issues/27060 [`UnsafeCell`]: ../std/cell/struct.UnsafeCell.html diff --git a/src/doc/reference/.github/workflows/main.yml b/src/doc/reference/.github/workflows/main.yml new file mode 100644 index 0000000000..dca743a23b --- /dev/null +++ b/src/doc/reference/.github/workflows/main.yml @@ -0,0 +1,32 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Update rustup + run: rustup self update + - name: Install Rust + run: | + rustup set profile minimal + rustup toolchain install nightly -c rust-docs + rustup default nightly + - name: Install mdbook + run: | + mkdir bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.3.4/mdbook-v0.3.4-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + echo "##[add-path]$(pwd)/bin" + - name: Report versions + run: | + rustup --version + rustc -Vv + mdbook --version + - name: Run tests + run: mdbook test + - name: Check for unstable features + run: (cd stable-check && cargo run -- ../src) + - name: Check for broken links + run: tests/linkcheck.sh diff --git a/src/doc/reference/.travis.yml b/src/doc/reference/.travis.yml deleted file mode 100644 index 73304507e5..0000000000 --- a/src/doc/reference/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: shell - -before_install: - - curl -sSL https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly --profile=minimal -c rust-docs - - export PATH="$HOME/.cargo/bin:$PATH" - -install: - - travis_retry curl -Lf https://github.com/rust-lang-nursery/mdBook/releases/download/v0.3.1/mdbook-v0.3.1-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=$HOME/.cargo/bin - -script: - - export PATH=$PATH:/home/travis/.cargo/bin && mdbook test - - (cd stable-check && cargo run -- ../src) - - tests/linkcheck.sh diff --git a/src/doc/reference/CONTRIBUTING.md b/src/doc/reference/CONTRIBUTING.md index 7d06ede6fd..75a7e83a8e 100644 --- a/src/doc/reference/CONTRIBUTING.md +++ b/src/doc/reference/CONTRIBUTING.md @@ -63,7 +63,7 @@ This should include links to any relevant information, such as the stabilization PR, the RFC, the tracking issue, and anything else that would be helpful for writing the documentation. -[issue tracker]: https://github.com/rust-lang-nursery/reference/issues +[issue tracker]: https://github.com/rust-lang/reference/issues [playpen]: https://play.rust-lang.org/ [rust-lang/rust]: https://github.com/rust-lang/rust/ [unstable]: https://doc.rust-lang.org/nightly/unstable-book/ diff --git a/src/doc/reference/book.toml b/src/doc/reference/book.toml index 05a93bb3d1..b1335de77c 100644 --- a/src/doc/reference/book.toml +++ b/src/doc/reference/book.toml @@ -5,4 +5,4 @@ author = "The Rust Project Developers" [output.html] additional-css = ["theme/reference.css"] -git-repository-url = "https://github.com/rust-lang-nursery/reference/" +git-repository-url = "https://github.com/rust-lang/reference/" diff --git a/src/doc/reference/src/abi.md b/src/doc/reference/src/abi.md index 2e9e969ac6..e4f1ec0317 100644 --- a/src/doc/reference/src/abi.md +++ b/src/doc/reference/src/abi.md @@ -68,7 +68,8 @@ The *`link_section` attribute* specifies the section of the object file that a [function] or [static]'s content will be placed into. It uses the [_MetaNameValueStr_] syntax to specify the section name. -```rust,ignore + +```rust,no_run #[no_mangle] #[link_section = ".example_section"] pub static VAR1: u32 = 1; @@ -80,7 +81,7 @@ The *`export_name` attribute* specifies the name of the symbol that will be exported on a [function] or [static]. It uses the [_MetaNameValueStr_] syntax to specify the symbol name. -```rust,ignore +```rust #[export_name = "exported_symbol_name"] pub fn name_in_rust() { } ``` diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md index c9ac02d5bc..5b504c13a3 100644 --- a/src/doc/reference/src/attributes/codegen.md +++ b/src/doc/reference/src/attributes/codegen.md @@ -49,7 +49,8 @@ enable code generation of that function for specific platform architecture features. It uses the [_MetaListNameValueStr_] syntax with a single key of `enable` whose value is a string of comma-separated feature names to enable. -```rust,ignore +```rust +# #[cfg(target_feature = "avx2")] #[target_feature(enable = "avx2")] unsafe fn foo_avx2() {} ``` diff --git a/src/doc/reference/src/attributes/type_system.md b/src/doc/reference/src/attributes/type_system.md index 52bbb68f18..97938f2d7a 100644 --- a/src/doc/reference/src/attributes/type_system.md +++ b/src/doc/reference/src/attributes/type_system.md @@ -66,7 +66,8 @@ Non-exhaustive types cannot be constructed outside of the defining crate: with a [_StructExpression_] \(including with [functional update syntax]). - [`enum`][enum] instances can be constructed in an [_EnumerationVariantExpression_]. -```rust,ignore (requires multiple crates) + +```rust,ignore // `Config`, `Error`, and `Message` are types defined in an upstream crate that have been // annotated as `#[non_exhaustive]`. use upstream::{Config, Error, Message}; @@ -99,7 +100,8 @@ There are limitations when matching on non-exhaustive types outside of the defin - When pattern matching on a non-exhaustive [`enum`][enum], matching on a variant does not contribute towards the exhaustiveness of the arms. -```rust, ignore (requires multiple crates) + +```rust, ignore // `Config`, `Error`, and `Message` are types defined in an upstream crate that have been // annotated as `#[non_exhaustive]`. use upstream::{Config, Error, Message}; diff --git a/src/doc/reference/src/conditional-compilation.md b/src/doc/reference/src/conditional-compilation.md index 5051282753..95285e3afb 100644 --- a/src/doc/reference/src/conditional-compilation.md +++ b/src/doc/reference/src/conditional-compilation.md @@ -264,6 +264,7 @@ When the configuration predicate is true, this attribute expands out to the attributes listed after the predicate. For example, the following module will either be found at `linux.rs` or `windows.rs` based on the target. + ```rust,ignore #[cfg_attr(linux, path = "linux.rs")] #[cfg_attr(windows, path = "windows.rs")] @@ -273,6 +274,7 @@ mod os; Zero, one, or more attributes may be listed. Multiple attributes will each be expanded into separate attributes. For example: + ```rust,ignore #[cfg_attr(feature = "magic", sparkles, crackles)] fn bewitched() {} diff --git a/src/doc/reference/src/crates-and-source-files.md b/src/doc/reference/src/crates-and-source-files.md index 1ab03d4bc1..1fb8425550 100644 --- a/src/doc/reference/src/crates-and-source-files.md +++ b/src/doc/reference/src/crates-and-source-files.md @@ -53,7 +53,7 @@ that apply to the containing module, most of which influence the behavior of the compiler. The anonymous crate module can have additional attributes that apply to the crate as a whole. -```rust,no_run +```rust // Specify the crate name. #![crate_name = "projx"] @@ -75,7 +75,8 @@ essentially to treat the source file as an executable script. The shebang can only occur at the beginning of the file (but after the optional _UTF8BOM_). It is ignored by the compiler. For example: -```text,ignore + +```rust,ignore #!/usr/bin/env rustx fn main() { @@ -136,7 +137,7 @@ other object being linked to defines `main`. The *`crate_name` [attribute]* may be applied at the crate level to specify the name of the crate with the [_MetaNameValueStr_] syntax. -```rust,ignore +```rust #![crate_name = "mycrate"] ``` diff --git a/src/doc/reference/src/expressions/array-expr.md b/src/doc/reference/src/expressions/array-expr.md index cf016acca7..f31fbb8743 100644 --- a/src/doc/reference/src/expressions/array-expr.md +++ b/src/doc/reference/src/expressions/array-expr.md @@ -12,7 +12,7 @@ An _[array](../types/array.md) expression_ can be written by enclosing zero or more comma-separated expressions of uniform type in square -brackets. This produces and array containing each of these values in the +brackets. This produces an array containing each of these values in the order they are written. Alternatively there can be exactly two expressions inside the brackets, diff --git a/src/doc/reference/src/expressions/await-expr.md b/src/doc/reference/src/expressions/await-expr.md index a6e7dc5831..85985c6f42 100644 --- a/src/doc/reference/src/expressions/await-expr.md +++ b/src/doc/reference/src/expressions/await-expr.md @@ -51,6 +51,7 @@ context, there must be some task context available. Effectively, an `.await` expression is roughly equivalent to the following (this desugaring is not normative): + ```rust,ignore match /* */ { mut pinned => loop { diff --git a/src/doc/reference/src/expressions/field-expr.md b/src/doc/reference/src/expressions/field-expr.md index d9a7b9218c..4e187a1b44 100644 --- a/src/doc/reference/src/expressions/field-expr.md +++ b/src/doc/reference/src/expressions/field-expr.md @@ -10,6 +10,7 @@ A _field expression_ consists of an expression followed by a single dot and an field of a [struct] or [union]. To call a function stored in a struct, parentheses are needed around the field expression. + ```rust,ignore mystruct.myfield; foo().x; diff --git a/src/doc/reference/src/expressions/if-expr.md b/src/doc/reference/src/expressions/if-expr.md index efe3849964..5d04bb5c70 100644 --- a/src/doc/reference/src/expressions/if-expr.md +++ b/src/doc/reference/src/expressions/if-expr.md @@ -97,6 +97,7 @@ assert_eq!(a, 3); An `if let` expression is equivalent to a [`match` expression] as follows: + ```rust,ignore if let PATS = EXPR { /* body */ @@ -107,6 +108,7 @@ if let PATS = EXPR { is equivalent to + ```rust,ignore match EXPR { PATS => { /* body */ }, @@ -135,6 +137,7 @@ of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLe When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below: + ```rust,ignore // Before... if let PAT = EXPR && EXPR { .. } diff --git a/src/doc/reference/src/expressions/loop-expr.md b/src/doc/reference/src/expressions/loop-expr.md index 67be5755ed..e37235a305 100644 --- a/src/doc/reference/src/expressions/loop-expr.md +++ b/src/doc/reference/src/expressions/loop-expr.md @@ -93,6 +93,7 @@ while let _ = 5 { A `while let` loop is equivalent to a `loop` expression containing a [`match` expression] as follows. + ```rust,ignore 'label: while let PATS = EXPR { /* loop body */ @@ -101,6 +102,7 @@ expression] as follows. is equivalent to + ```rust,ignore 'label: loop { match EXPR { @@ -156,6 +158,7 @@ assert_eq!(sum, 55); A for loop is equivalent to the following block expression. + ```rust,ignore 'label: for PATTERN in iter_expr { /* loop body */ @@ -164,6 +167,7 @@ A for loop is equivalent to the following block expression. is equivalent to + ```rust,ignore { let result = match IntoIterator::into_iter(iter_expr) { diff --git a/src/doc/reference/src/expressions/match-expr.md b/src/doc/reference/src/expressions/match-expr.md index aea103326f..dcbf69fe73 100644 --- a/src/doc/reference/src/expressions/match-expr.md +++ b/src/doc/reference/src/expressions/match-expr.md @@ -91,10 +91,11 @@ Every binding in each `|` separated pattern must appear in all of the patterns in the arm. Every binding of the same name must have the same type, and have the same binding mode. +## Match guards + Match arms can accept _match guards_ to further refine the criteria for matching a case. Pattern guards appear after the pattern and -consist of a bool-typed expression following the `if` keyword. A pattern guard -may refer to the variables bound within the pattern they follow. +consist of a `bool`-typed expression following the `if` keyword. When the pattern matches successfully, the pattern guard expression is executed. If the expression evaluates to true, the pattern is successfully matched against. @@ -125,6 +126,16 @@ let message = match maybe_digit { > assert_eq!(i.get(), 2); > ``` +A pattern guard may refer to the variables bound within the pattern they follow. +Before evaluating the guard, a shared reference is taken to the part of the +scrutinee the variable matches on. While evaluating the guard, +this shared reference is then used when accessing the variable. +Only when the guard evaluates to true is the value moved, or copied, +from the scrutinee into the variable. This allows shared borrows to be used +inside guards without moving out of the scrutinee in case guard fails to match. +Moreover, by holding a shared reference while evaluating the guard, +mutation inside guards is also prevented. + ## Attributes on match arms Outer attributes are allowed on match arms. The only attributes that have diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md index 3635cc0328..b0f8c017eb 100644 --- a/src/doc/reference/src/expressions/operator-expr.md +++ b/src/doc/reference/src/expressions/operator-expr.md @@ -260,7 +260,9 @@ functions and macros in the standard library can then use that assumption above, these operators implicitly take shared borrows of their operands, evaluating them in [place expression context][place expression]: -```rust,ignore +```rust +# let a = 1; +# let b = 1; a == b; // is equivalent to ::std::cmp::PartialEq::eq(&a, &b); diff --git a/src/doc/reference/src/glossary.md b/src/doc/reference/src/glossary.md index 36c0c9314a..65b1978d04 100644 --- a/src/doc/reference/src/glossary.md +++ b/src/doc/reference/src/glossary.md @@ -30,6 +30,14 @@ items are defined in [implementations] and declared in [traits]. Only functions, constants, and type aliases can be associated. Contrast to a [free item]. +### Blanket implementation + +Any implementation where a type appears [uncovered](#uncovered-type). `impl Foo +for T`, `impl Bar for T`, `impl Bar> for T`, and `impl Bar +for Vec` are considered blanket impls. However, `impl Bar> for +Vec` is not a blanket impl, as all instances of `T` which appear in this `impl` +are covered by `Vec`. + ### Bound Bounds are constraints on a type or trait. For example, if a bound @@ -65,6 +73,21 @@ For example, `2 + (3 * 4)` is an expression that returns the value 14. An [item] that is not a member of an [implementation], such as a *free function* or a *free const*. Contrast to an [associated item]. +### Fundamental traits + +A fundamental trait is one where adding an impl of it for an existing type is a breaking change. +The `Fn` traits and `Sized` are fundamental. + +### Fundamental type constructors + +A fundamental type constructor is a type where implementing a [blanket implementation](#blanket-implementation) over it +is a breaking change. `&`, `&mut`, `Box`, and `Pin` are fundamental. + +Any time a type `T` is considered [local](#local-type), `&T`, `&mut T`, `Box`, and `Pin` +are also considered local. Fundamental type constructors cannot [cover](#uncovered-type) other types. +Any time the term "covered type" is used, +the `T` in `&T`, `&mut T`, `Box`, and `Pin` is not considered covered. + ### Inhabited A type is inhabited if it has constructors and therefore can be instantiated. An inhabited type is @@ -87,6 +110,19 @@ A variable is initialized if it has been assigned a value and hasn't since been moved from. All other memory locations are assumed to be uninitialized. Only unsafe Rust can create such a memory without initializing it. +### Local trait + +A `trait` which was defined in the current crate. A trait definition is local +or not independent of applied type arguments. Given `trait Foo`, +`Foo` is always local, regardless of the types substituted for `T` and `U`. + +### Local type + +A `struct`, `enum`, or `union` which was defined in the current crate. +This is not affected by applied type arguments. `struct Foo` is considered local, but +`Vec` is not. `LocalType` is local. Type aliases do not +affect locality. + ### Nominal types Types that can be referred to by a path directly. Specifically [enums], @@ -158,6 +194,12 @@ It allows a type to make certain promises about its behavior. Generic functions and generic structs can use traits to constrain, or bound, the types they accept. +### Uncovered type + +A type which does not appear as an argument to another type. For example, +`T` is uncovered, but the `T` in `Vec` is covered. This is only relevant for +type arguments. + ### Undefined behavior Compile-time or run-time behavior that is not specified. This may result in, diff --git a/src/doc/reference/src/introduction.md b/src/doc/reference/src/introduction.md index 873fa0c418..2ef5413d59 100644 --- a/src/doc/reference/src/introduction.md +++ b/src/doc/reference/src/introduction.md @@ -132,9 +132,9 @@ hesitate to file an issue or ask about it in the `#docs` channels on attention to making those sections the best that they can be. [book]: ../book/index.html -[github issues]: https://github.com/rust-lang-nursery/reference/issues +[github issues]: https://github.com/rust-lang/reference/issues [standard library]: ../std/index.html -[the Rust Reference repository]: https://github.com/rust-lang-nursery/reference/ +[the Rust Reference repository]: https://github.com/rust-lang/reference/ [Unstable Book]: https://doc.rust-lang.org/nightly/unstable-book/ [_Expression_]: expressions.md [cargo book]: ../cargo/index.html diff --git a/src/doc/reference/src/items/associated-items.md b/src/doc/reference/src/items/associated-items.md index a7bc3de86d..c1f82f62ec 100644 --- a/src/doc/reference/src/items/associated-items.md +++ b/src/doc/reference/src/items/associated-items.md @@ -18,7 +18,7 @@ Every associated item kind comes in two varieties: definitions that contain the actual implementation and declarations that declare signatures for definitions. -It is the declarations that make up the contract of traits and what it available +It is the declarations that make up the contract of traits and what is available on generic types. ## Associated functions and methods @@ -360,4 +360,4 @@ fn main() { [function item]: ../types/function-item.md [method call operator]: ../expressions/method-call-expr.md [path]: ../paths.md -[regular function parameters]: functions.md#attributes-on-function-parameters \ No newline at end of file +[regular function parameters]: functions.md#attributes-on-function-parameters diff --git a/src/doc/reference/src/items/enumerations.md b/src/doc/reference/src/items/enumerations.md index 8779f61bb8..25dfecb656 100644 --- a/src/doc/reference/src/items/enumerations.md +++ b/src/doc/reference/src/items/enumerations.md @@ -12,7 +12,7 @@ >    _EnumItem_ ( `,` _EnumItem_ )\* `,`? > > _EnumItem_ :\ ->    _OuterAttribute_\*\ +>    _OuterAttribute_\* [_Visibility_]?\ >    [IDENTIFIER] ( _EnumItemTuple_ | _EnumItemStruct_ > | _EnumItemDiscriminant_ )? > @@ -91,7 +91,7 @@ using a [primitive representation] or the [`C` representation]. It is an error when two variants share the same discriminant. -```rust,ignore +```rust,compile_fail enum SharedDiscriminantError { SharedA = 1, SharedB = 1 @@ -107,7 +107,7 @@ enum SharedDiscriminantError2 { It is also an error to have an unspecified discriminant where the previous discriminant is the maximum value for the size of the discriminant. -```rust,ignore +```rust,compile_fail #[repr(u8)] enum OverflowingDiscriminantError { Max = 255, @@ -131,14 +131,56 @@ no valid values, they cannot be instantiated. enum ZeroVariants {} ``` +Zero-variant enums are equivalent to the [never type], but they cannot be +coerced into other types. + +```rust,compile_fail +# enum ZeroVariants {} +let x: ZeroVariants = panic!(); +let y: u32 = x; // mismatched type error +``` + +## Variant visibility + +Enum variants syntactically allow a [_Visibility_] annotation, but this is +rejected when the enum is validated. This allows items to be parsed with a +unified syntax across different contexts where they are used. + +```rust +macro_rules! mac_variant { + ($vis:vis $name:ident) => { + enum $name { + $vis Unit, + + $vis Tuple(u8, u16), + + $vis Struct { f: u8 }, + } + } +} + +// Empty `vis` is allowed. +mac_variant! { E } + +// This is allowed, since it is removed before being validated. +#[cfg(FALSE)] +enum E { + pub U, + pub(crate) T(u8), + pub(super) T { f: String } +} +``` + [IDENTIFIER]: ../identifiers.md [_Generics_]: generics.md [_WhereClause_]: generics.md#where-clauses [_Expression_]: ../expressions.md [_TupleFields_]: structs.md [_StructFields_]: structs.md +[_Visibility_]: ../visibility-and-privacy.md [enumerated type]: ../types/enum.md [`mem::discriminant`]: ../../std/mem/fn.discriminant.html +[never type]: ../types/never.md [numeric cast]: ../expressions/operator-expr.md#semantics [constant expression]: ../const_eval.md#constant-expressions [default representation]: ../type-layout.md#the-default-representation diff --git a/src/doc/reference/src/items/extern-crates.md b/src/doc/reference/src/items/extern-crates.md index ff66d50be9..eb5c2eb8ce 100644 --- a/src/doc/reference/src/items/extern-crates.md +++ b/src/doc/reference/src/items/extern-crates.md @@ -28,6 +28,7 @@ In this case the `as` clause must be used to specify the name to bind it to. Three examples of `extern crate` declarations: + ```rust,ignore extern crate pcre; @@ -43,6 +44,7 @@ details). Here is an example: + ```rust,ignore // Importing the Cargo package hello-world extern crate hello_world; // hyphen replaced with an underscore diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md index 6537084279..211a2fa4c2 100644 --- a/src/doc/reference/src/items/external-blocks.md +++ b/src/doc/reference/src/items/external-blocks.md @@ -64,7 +64,7 @@ By default external blocks assume that the library they are calling uses the standard C ABI on the specific platform. Other ABIs may be specified using an `abi` string, as shown here: -```rust,ignore +```rust // Interface to the Windows API extern "stdcall" { } ``` @@ -97,7 +97,7 @@ There are also some platform-specific ABI strings: Functions within external blocks may be variadic by specifying `...` after one or more named arguments in the argument list: -```rust,ignore +```rust extern { fn foo(x: i32, ...); } @@ -128,6 +128,7 @@ name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. + ```rust,ignore #[link(name = "crypto")] extern { @@ -156,7 +157,7 @@ The `link_name` attribute may be specified on declarations inside an `extern` block to indicate the symbol to import for the given function or static. It uses the [_MetaNameValueStr_] syntax to specify the name of the symbol. -```rust,ignore +```rust extern { #[link_name = "actual_symbol_name"] fn name_in_rust(); @@ -184,4 +185,4 @@ restrictions as [regular function parameters]. [_Visibility_]: ../visibility-and-privacy.md [_WhereClause_]: generics.md#where-clauses [attributes]: ../attributes.md -[regular function parameters]: functions.md#attributes-on-function-parameters \ No newline at end of file +[regular function parameters]: functions.md#attributes-on-function-parameters diff --git a/src/doc/reference/src/items/functions.md b/src/doc/reference/src/items/functions.md index 4bc48518f6..fce59050e4 100644 --- a/src/doc/reference/src/items/functions.md +++ b/src/doc/reference/src/items/functions.md @@ -58,6 +58,7 @@ the body of the function will short-cut that implicit return, if reached. For example, the function above behaves as if it was written as: + ```rust,ignore // argument_0 is the actual first argument passed from the caller let (value, _) = argument_0; @@ -115,14 +116,16 @@ sufficient context to determine the type parameters. For example, The `extern` function qualifier allows providing function _definitions_ that can be called with a particular ABI: ++ ```rust,ignore -extern "ABI" fn foo() { ... } +extern "ABI" fn foo() { /* ... */ } ``` These are often used in combination with [external block] items which provide function _declarations_ that can be used to call functions without providing their _definition_: ++ ```rust,ignore extern "ABI" { fn foo(); /* no body */ @@ -376,6 +379,7 @@ For example, the following code defines an inert `some_inert_attribute` attribut is not formally defined anywhere and the `some_proc_macro_attribute` procedural macro is responsible for detecting its presence and removing it from the output token stream. + ```rust,ignore #[some_proc_macro_attribute] fn foo_oof(#[some_inert_attribute] arg: u8) { diff --git a/src/doc/reference/src/items/generics.md b/src/doc/reference/src/items/generics.md index 6dc8f01d09..ba35e64d25 100644 --- a/src/doc/reference/src/items/generics.md +++ b/src/doc/reference/src/items/generics.md @@ -69,7 +69,7 @@ types when defining the item. It is an error to have `Copy` or `Clone`as a bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a bound on a trait object or slice. -```rust,ignore +```rust,compile_fail struct A where T: Iterator, // Could use A instead @@ -92,6 +92,7 @@ attributes may give meaning to it. This example shows using a custom derive attribute to modify the meaning of a generic parameter. + ```rust,ignore // Assume that the derive for MyFlexibleClone declared `my_flexible_clone` as // an attribute it understands. diff --git a/src/doc/reference/src/items/implementations.md b/src/doc/reference/src/items/implementations.md index fedc4c18c9..c4e63b2faa 100644 --- a/src/doc/reference/src/items/implementations.md +++ b/src/doc/reference/src/items/implementations.md @@ -152,7 +152,7 @@ impl Shape for Circle { ### Trait Implementation Coherence -A trait implementation is considered incoherent if either the orphan check fails +A trait implementation is considered incoherent if either the orphan rules check fails or there are overlapping implementation instances. Two trait implementations overlap when there is a non-empty intersection of the @@ -160,21 +160,23 @@ traits the implementation is for, the implementations can be instantiated with the same type. -The `Orphan Check` states that every trait implementation must meet either of -the following conditions: +#### Orphan rules -1. The trait being implemented is defined in the same crate. +Given `impl Trait for T0`, an `impl` is valid only if at +least one of the following is true: -2. At least one of either `Self` or a generic type parameter of the trait must - meet the following grammar, where `C` is a nominal type defined - within the containing crate: +- `Trait` is a [local trait] +- All of + - At least one of the types `T0..=Tn` must be a [local type]. Let `Ti` be the + first such type. + - No [uncovered type] parameters `P1..=Pn` may appear in `T0..Ti` (excluding + `Ti`) + +Only the appearance of *uncovered* type parameters is restricted. +Note that for the purposes of coherence, [fundamental types] are +special. The `T` in `Box` is not considered covered, and `Box` +is considered local. - ```ignore - T = C - | &C - | &mut C - | Box - ``` ## Generic Implementations @@ -224,3 +226,7 @@ attributes]. [path]: ../paths.md [the lint check attributes]: ../attributes/diagnostics.md#lint-check-attributes [Unsafe traits]: traits.md#unsafe-traits +[local trait]: ../glossary.md#local-trait +[local type]: ../glossary.md#local-type +[fundamental types]: ../glossary.md#fundamental-type-constructors +[uncovered type]: ../glossary.md#uncovered-type diff --git a/src/doc/reference/src/items/modules.md b/src/doc/reference/src/items/modules.md index c6f1f69c13..a58bd37a2d 100644 --- a/src/doc/reference/src/items/modules.md +++ b/src/doc/reference/src/items/modules.md @@ -74,6 +74,7 @@ For `path` attributes on modules not inside inline module blocks, the file path is relative to the directory the source file is located. For example, the following code snippet would use the paths shown based on where it is located: + ```rust,ignore #[path = "foo.rs"] mod c; @@ -95,6 +96,7 @@ it is the same except the path starts with a directory with the name of the non-mod-rs module. For example, the following code snippet would use the paths shown based on where it is located: + ```rust,ignore mod inline { #[path = "other.rs"] @@ -110,6 +112,7 @@ Source File | `inner`'s File Location | `inner`'s Module Path An example of combining the above rules of `path` attributes on inline modules and nested modules within (applies to both mod-rs and non-mod-rs files): + ```rust,ignore #[path = "thread_files"] mod thread { @@ -127,7 +130,7 @@ macros imported with [`#[macro_use]`][macro_use] on an extern crate, and by the [prelude]. These names are all made of a single identifier. These names are not part of the module, so for example, any name `name`, `self::name` is not a valid path. The names added by the [prelude] can be removed by placing the -`no_implicit_prelude` [attribute] onto the module. +`no_implicit_prelude` [attribute] onto the module or one of its ancestor modules. ## Attributes on Modules diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md index dea8ecad05..5427dbe652 100644 --- a/src/doc/reference/src/items/traits.md +++ b/src/doc/reference/src/items/traits.md @@ -10,7 +10,7 @@ >    `}` > > _TraitItem_ :\ ->    [_OuterAttribute_]\* (\ +>    [_OuterAttribute_]\* [_Visibility_]? (\ >          _TraitFunc_\ >       | _TraitMethod_\ >       | _TraitConst_\ @@ -204,6 +204,42 @@ trait T { } ``` +## Item visibility + +Trait items syntactically allow a [_Visibility_] annotation, but this is +rejected when the trait is validated. This allows items to be parsed with a +unified syntax across different contexts where they are used. As an example, +an empty `vis` macro fragment specifier can be used for trait items, where the +macro rule may be used in other situations where visibility is allowed. + +```rust +macro_rules! create_method { + ($vis:vis $name:ident) => { + $vis fn $name(&self) {} + }; +} + +trait T1 { + // Empty `vis` is allowed. + create_method! { method_of_t1 } +} + +struct S; + +impl S { + // Visibility is allowed here. + create_method! { pub method_of_s } +} + +impl T1 for S {} + +fn main() { + let s = S; + s.method_of_t1(); + s.method_of_s(); +} +``` + [IDENTIFIER]: ../identifiers.md [WildcardPattern]: ../patterns.md#wildcard-pattern [_BlockExpression_]: ../expressions/block-expr.md @@ -217,6 +253,7 @@ trait T { [_SelfParam_]: associated-items.md#methods [_TypeParamBounds_]: ../trait-bounds.md [_Type_]: ../types.md#type-expressions +[_Visibility_]: ../visibility-and-privacy.md [_WhereClause_]: generics.md#where-clauses [bounds]: ../trait-bounds.md [trait object]: ../types/trait-object.md diff --git a/src/doc/reference/src/items/unions.md b/src/doc/reference/src/items/unions.md index d63bf1eec9..7555a47b00 100644 --- a/src/doc/reference/src/items/unions.md +++ b/src/doc/reference/src/items/unions.md @@ -35,8 +35,11 @@ The expression above creates a value of type `MyUnion` and initializes the storage using field `f1`. The union can be accessed using the same syntax as struct fields: -```rust,ignore -let f = u.f1; +```rust +# union MyUnion { f1: u32, f2: f32 } +# +# let u = MyUnion { f1: 1 }; +let f = unsafe { u.f1 }; ``` ## Reading and writing union fields @@ -135,18 +138,19 @@ have to be adjusted to account for this fact. As a result, if one field of a union is borrowed, all its remaining fields are borrowed as well for the same lifetime. -```rust,ignore +```rust,compile_fail +# union MyUnion { f1: u32, f2: f32 } // ERROR: cannot borrow `u` (via `u.f2`) as mutable more than once at a time fn test() { let mut u = MyUnion { f1: 1 }; unsafe { let b1 = &mut u.f1; - ---- first mutable borrow occurs here (via `u.f1`) +// ---- first mutable borrow occurs here (via `u.f1`) let b2 = &mut u.f2; - ^^^^ second mutable borrow occurs here (via `u.f2`) +// ^^^^ second mutable borrow occurs here (via `u.f2`) *b1 = 5; } - - first borrow ends here +// - first borrow ends here assert_eq!(unsafe { u.f1 }, 5); } ``` diff --git a/src/doc/reference/src/items/use-declarations.md b/src/doc/reference/src/items/use-declarations.md index 4397fc4bd4..92bd780843 100644 --- a/src/doc/reference/src/items/use-declarations.md +++ b/src/doc/reference/src/items/use-declarations.md @@ -98,7 +98,7 @@ use crate::foo::baz::foobaz; // good: foo is at the root of the crate mod foo { - mod example { + pub mod example { pub mod iter {} } @@ -124,9 +124,14 @@ fn main() {} > accessing items in the crate root. Using the example above, the following > `use` paths work in 2015 but not 2018: > -> ```rust,ignore +> ```rust,edition2015 +> # mod foo { +> # pub mod example { pub mod iter {} } +> # pub mod baz { pub fn foobaz() {} } +> # } > use foo::example::iter; > use ::foo::baz::foobaz; +> # fn main() {} > ``` > > The 2015 edition does not allow use declarations to reference the [extern prelude]. diff --git a/src/doc/reference/src/lifetime-elision.md b/src/doc/reference/src/lifetime-elision.md index 51a03ef75c..201e34410c 100644 --- a/src/doc/reference/src/lifetime-elision.md +++ b/src/doc/reference/src/lifetime-elision.md @@ -25,36 +25,52 @@ In method signatures there is another rule Examples: -```rust,ignore -fn print(s: &str); // elided -fn print(s: &'_ str); // also elided -fn print<'a>(s: &'a str); // expanded - -fn debug(lvl: usize, s: &str); // elided -fn debug<'a>(lvl: usize, s: &'a str); // expanded - -fn substr(s: &str, until: usize) -> &str; // elided -fn substr<'a>(s: &'a str, until: usize) -> &'a str; // expanded - -fn get_str() -> &str; // ILLEGAL - -fn frob(s: &str, t: &str) -> &str; // ILLEGAL - -fn get_mut(&mut self) -> &mut T; // elided -fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded - -fn args(&mut self, args: &[T]) -> &mut Command; // elided -fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded +```rust +# trait T {} +# trait ToCStr {} +# struct Thing<'a> {f: &'a i32} +# struct Command; +# +# trait Example { +fn print1(s: &str); // elided +fn print2(s: &'_ str); // also elided +fn print3<'a>(s: &'a str); // expanded + +fn debug1(lvl: usize, s: &str); // elided +fn debug2<'a>(lvl: usize, s: &'a str); // expanded + +fn substr1(s: &str, until: usize) -> &str; // elided +fn substr2<'a>(s: &'a str, until: usize) -> &'a str; // expanded + +fn get_mut1(&mut self) -> &mut dyn T; // elided +fn get_mut2<'a>(&'a mut self) -> &'a mut dyn T; // expanded + +fn args1(&mut self, args: &[T]) -> &mut Command; // elided +fn args2<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded + +fn new1(buf: &mut [u8]) -> Thing<'_>; // elided - preferred +fn new2(buf: &mut [u8]) -> Thing; // elided +fn new3<'a>(buf: &'a mut [u8]) -> Thing<'a>; // expanded +# } + +type FunPtr1 = fn(&str) -> &str; // elided +type FunPtr2 = for<'a> fn(&'a str) -> &'a str; // expanded + +type FunTrait1 = dyn Fn(&str) -> &str; // elided +type FunTrait2 = dyn for<'a> Fn(&'a str) -> &'a str; // expanded +``` -fn new(buf: &mut [u8]) -> BufWriter<'_>; // elided - preferred -fn new(buf: &mut [u8]) -> BufWriter; // elided -fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded +```rust,compile_fail +// The following examples show situations where it is not allowed to elide the +// lifetime parameter. -type FunPtr = fn(&str) -> &str; // elided -type FunPtr = for<'a> fn(&'a str) -> &'a str; // expanded +# trait Example { +// Cannot infer, because there are no parameters to infer from. +fn get_str() -> &str; // ILLEGAL -type FunTrait = dyn Fn(&str) -> &str; // elided -type FunTrait = dyn for<'a> Fn(&'a str) -> &'a str; // expanded +// Cannot infer, ambiguous if it is borrowed from the first or second parameter. +fn frob(s: &str, t: &str) -> &str; // ILLEGAL +# } ``` ## Default trait object lifetimes @@ -83,50 +99,54 @@ If neither of those rules apply, then the bounds on the trait are used: * If the trait has no lifetime bounds, then the lifetime is inferred in expressions and is `'static` outside of expressions. -```rust,ignore +```rust // For the following trait... trait Foo { } // These two are the same as Box has no lifetime bound on T -Box -Box +type T1 = Box; +type T2 = Box; // ...and so are these: impl dyn Foo {} impl dyn Foo + 'static {} // ...so are these, because &'a T requires T: 'a -&'a dyn Foo -&'a (dyn Foo + 'a) +type T3<'a> = &'a dyn Foo; +type T4<'a> = &'a (dyn Foo + 'a); // std::cell::Ref<'a, T> also requires T: 'a, so these are the same -std::cell::Ref<'a, dyn Foo> -std::cell::Ref<'a, dyn Foo + 'a> +type T5<'a> = std::cell::Ref<'a, dyn Foo>; +type T6<'a> = std::cell::Ref<'a, dyn Foo + 'a>; +``` -// This is an error: -struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b> -TwoBounds<'a, 'b, dyn Foo> // Error: the lifetime bound for this object type - // cannot be deduced from context +```rust,compile_fail +// This is an example of an error. +# trait Foo { } +struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b> { + f1: &'a i32, + f2: &'b i32, + f3: T, +} +type T7<'a, 'b> = TwoBounds<'a, 'b, dyn Foo>; +// ^^^^^^^ +// Error: the lifetime bound for this object type cannot be deduced from context ``` Note that the innermost object sets the bound, so `&'a Box` is still `&'a Box`. -```rust,ignore +```rust // For the following trait... trait Bar<'a>: 'a { } // ...these two are the same: -Box> -Box + 'a> +type T1<'a> = Box>; +type T2<'a> = Box + 'a>; // ...and so are these: -impl<'a> dyn Foo<'a> {} -impl<'a> dyn Foo<'a> + 'a {} - -// This is still an error: -struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b> -TwoBounds<'a, 'b, dyn Foo<'c>> +impl<'a> dyn Bar<'a> {} +impl<'a> dyn Bar<'a> + 'a {} ``` ## `'static` lifetime elision @@ -157,16 +177,29 @@ references, which themselves include references, the compiler will first try the standard elision rules. If it is unable to resolve the lifetimes by its usual rules, then it will error. By way of example: -```rust,ignore +```rust +# struct Foo; +# struct Bar; +# struct Baz; +# fn somefunc(a: &Foo, b: &Bar, c: &Baz) -> usize {42} // Resolved as `fn<'a>(&'a str) -> &'a str`. -const RESOLVED_SINGLE: fn(&str) -> &str = .. +const RESOLVED_SINGLE: fn(&str) -> &str = |x| x; // Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`. -const RESOLVED_MULTIPLE: &dyn Fn(&Foo, &Bar, &Baz) -> usize = .. +const RESOLVED_MULTIPLE: &dyn Fn(&Foo, &Bar, &Baz) -> usize = &somefunc; +``` +```rust,compile_fail +# struct Foo; +# struct Bar; +# struct Baz; +# fn somefunc<'a,'b>(a: &'a Foo, b: &'b Bar) -> &'a Baz {unimplemented!()} // There is insufficient information to bound the return reference lifetime // relative to the argument lifetimes, so this is an error. -const RESOLVED_STATIC: &dyn Fn(&Foo, &Bar) -> &Baz = .. +const RESOLVED_STATIC: &dyn Fn(&Foo, &Bar) -> &Baz = &somefunc; +// ^ +// this function's return type contains a borrowed value, but the signature +// does not say whether it is borrowed from argument 1 or argument 2 ``` [closure trait]: types/closure.md diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md index 61a24f2a27..5464aef729 100644 --- a/src/doc/reference/src/linkage.md +++ b/src/doc/reference/src/linkage.md @@ -151,13 +151,13 @@ feature. These target features are typically configured from the command line via flags to the compiler itself. For example to enable a static runtime you would execute: -```notrust +```bash rustc -C target-feature=+crt-static foo.rs ``` whereas to link dynamically to the C runtime you would execute: -```notrust +```bash rustc -C target-feature=-crt-static foo.rs ``` @@ -170,7 +170,7 @@ example, needs to be compiled differently (e.g. with `/MT` or `/MD`) depending on the runtime being linked. This is exported currently through the [`cfg` attribute `target_feature` option]: -```rust,ignore +```rust #[cfg(target_feature = "crt-static")] fn foo() { println!("the C runtime should be statically linked"); @@ -206,7 +206,7 @@ To use this feature locally, you typically will use the `RUSTFLAGS` environment variable to specify flags to the compiler through Cargo. For example to compile a statically linked binary on MSVC you would execute: -```ignore,notrust +```bash RUSTFLAGS='-C target-feature=+crt-static' cargo build --target x86_64-pc-windows-msvc ``` diff --git a/src/doc/reference/src/macros-by-example.md b/src/doc/reference/src/macros-by-example.md index fd7c33575a..34c2d4af9c 100644 --- a/src/doc/reference/src/macros-by-example.md +++ b/src/doc/reference/src/macros-by-example.md @@ -195,6 +195,7 @@ path), it is first looked up in textual scoping. If this does not yield any results, then it is looked up in path-based scoping. If the macro's name is qualified with a path, then it is only looked up in path-based scoping. + ```rust,ignore use lazy_static::lazy_static; // Path-based import. @@ -216,6 +217,7 @@ be used recursively, since names are looked up from the invocation site), up until its surrounding scope, typically a module, is closed. This can enter child modules and even span across multiple files: + ```rust,ignore //// src/lib.rs mod has_macro { @@ -306,6 +308,7 @@ conflict, the last macro imported wins. Optionally, a list of macros to import can be specified using the [_MetaListIdents_] syntax; this is not supported when `#[macro_use]` is applied to a module. + ```rust,ignore #[macro_use(lazy_static)] // Or #[macro_use] to import all macros. extern crate lazy_static; @@ -351,6 +354,7 @@ refers to an item or macro which isn't in scope at the invocation site. To alleviate this, the `$crate` metavariable can be used at the start of a path to force lookup to occur inside the crate defining the macro. + ```rust,ignore //// Definitions in the `helper_macro` crate. #[macro_export] diff --git a/src/doc/reference/src/paths.md b/src/doc/reference/src/paths.md index 5f13598df4..af739d7082 100644 --- a/src/doc/reference/src/paths.md +++ b/src/doc/reference/src/paths.md @@ -8,6 +8,7 @@ item. Two examples of simple paths consisting of only identifier segments: + ```rust,ignore x; x::y::z; @@ -135,10 +136,20 @@ and qualified paths. Although the `::` token is allowed before the generics arguments, it is not required because there is no ambiguity like there is in _PathInExpression_. -```rust,ignore +```rust +# mod ops { +# pub struct Range {f1: T} +# pub trait Index {} +# pub struct Example<'a> {f1: &'a i32} +# } +# struct S; impl ops::Index> for S { /*...*/ } -fn i() -> impl Iterator> { /*...*/ } -type G = std::boxed::Box isize>; +fn i<'a>() -> impl Iterator> { + // ... +# const EXAMPLE: Vec> = Vec::new(); +# EXAMPLE.into_iter() +} +type G = std::boxed::Box isize>; ``` ## Path qualifiers diff --git a/src/doc/reference/src/procedural-macros.md b/src/doc/reference/src/procedural-macros.md index ff3f6df1d7..2bd3706a28 100644 --- a/src/doc/reference/src/procedural-macros.md +++ b/src/doc/reference/src/procedural-macros.md @@ -80,7 +80,9 @@ output [`TokenStream`] replaces the entire macro invocation. For example, the following macro definition ignores its input and outputs a function `answer` into its scope. + ```rust,ignore +# #![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::TokenStream; @@ -92,6 +94,7 @@ pub fn make_answer(_item: TokenStream) -> TokenStream { And then we use it a binary crate to print "42" to standard output. + ```rust,ignore extern crate proc_macro_examples; use proc_macro_examples::make_answer; @@ -127,7 +130,9 @@ then appended to the [module] or [block] that the item from the input The following is an example of a derive macro. Instead of doing anything useful with its input, it just appends a function `answer`. + ```rust,ignore +# #![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::TokenStream; @@ -139,6 +144,7 @@ pub fn derive_answer_fn(_item: TokenStream) -> TokenStream { And then using said derive macro: + ```rust,ignore extern crate proc_macro_examples; use proc_macro_examples::AnswerFn; @@ -165,8 +171,9 @@ the names of the helper attributes. For example, the following derive macro defines a helper attribute `helper`, but ultimately doesn't do anything with it. + ```rust,ignore -# #[crate_type="proc-macro"] +# #![crate_type="proc-macro"] # extern crate proc_macro; # use proc_macro::TokenStream; @@ -178,11 +185,8 @@ pub fn derive_helper_attr(_item: TokenStream) -> TokenStream { And then usage on the derive macro on a struct: + ```rust,ignore -# #![crate_type="proc-macro"] -# extern crate proc_macro_examples; -# use proc_macro_examples::HelperAttr; - #[derive(HelperAttr)] struct Struct { #[helper] field: () @@ -207,6 +211,7 @@ replaces the [item] with an arbitrary number of [items]. For example, this attribute macro takes the input stream and returns it as is, effectively being the no-op of attributes. + ```rust,ignore # #![crate_type = "proc-macro"] # extern crate proc_macro; @@ -222,6 +227,7 @@ This following example shows the stringified [`TokenStream`s] that the attribute macros see. The output will show in the output of the compiler. The output is shown in the comments after the function prefixed with "out:". + ```rust,ignore // my-macro/src/lib.rs # extern crate proc_macro; @@ -235,6 +241,7 @@ pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream { } ``` + ```rust,ignore // src/lib.rs extern crate my_macro; diff --git a/src/doc/reference/src/runtime.md b/src/doc/reference/src/runtime.md index 57680d051e..06966926d9 100644 --- a/src/doc/reference/src/runtime.md +++ b/src/doc/reference/src/runtime.md @@ -12,9 +12,8 @@ The *`panic_handler` attribute* can only be applied to a function with signature Below is shown a `panic_handler` function that logs the panic message and then halts the thread. - - -``` rust, ignore + +```rust,ignore #![no_std] use core::fmt::{self, Write}; @@ -64,7 +63,7 @@ the [subsystem] when linking on a Windows target. It uses the `console` or `windows`. This attribute is ignored on non-Windows targets, and for non-`bin` [crate types]. -```rust,ignore +```rust #![windows_subsystem = "windows"] ``` diff --git a/src/doc/reference/src/special-types-and-traits.md b/src/doc/reference/src/special-types-and-traits.md index 9c2e0b1ff5..24a034de25 100644 --- a/src/doc/reference/src/special-types-and-traits.md +++ b/src/doc/reference/src/special-types-and-traits.md @@ -60,8 +60,12 @@ type is to be destroyed. The [`Copy`] trait changes the semantics of a type implementing it. Values whose type implements `Copy` are copied rather than moved upon assignment. -`Copy` cannot be implemented for types which implement `Drop`, or which have -fields that are not `Copy`. `Copy` is implemented by the compiler for + +`Copy` can only be implemented for types which do not implement `Drop`, and whose fields are all `Copy`. +For enums, this means all fields of all variants have to be `Copy`. +For unions, this means all variants have to be `Copy`. + +`Copy` is implemented by the compiler for * [Numeric types] * `char`, `bool`, and [`!`] diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md index 649bee4354..e4338f06fd 100644 --- a/src/doc/reference/src/tokens.md +++ b/src/doc/reference/src/tokens.md @@ -414,7 +414,7 @@ let a: u64 = 123; // type u64 Examples of invalid integer literals: -```rust,ignore +```rust,compile_fail // invalid suffixes 0invalidSuffix; diff --git a/src/doc/reference/src/trait-bounds.md b/src/doc/reference/src/trait-bounds.md index 6c48e5e6ff..fe677a9a1d 100644 --- a/src/doc/reference/src/trait-bounds.md +++ b/src/doc/reference/src/trait-bounds.md @@ -104,9 +104,11 @@ Type bounds may be *higher ranked* over lifetimes. These bounds specify a bound is true *for all* lifetimes. For example, a bound such as `for<'a> &'a T: PartialEq` would require an implementation like -```rust,ignore +```rust +# struct T; impl<'a> PartialEq for &'a T { // ... +# fn eq(&self, other: &i32) -> bool {true} } ``` diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index 57e801e105..900c6d4ac2 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -195,6 +195,7 @@ multiple of the struct's alignment. Here is this algorithm described in pseudocode. + ```rust,ignore struct.alignment = struct.fields().map(|field| field.alignment).max(); diff --git a/src/doc/reference/src/types/closure.md b/src/doc/reference/src/types/closure.md index 6ef5e6b6ef..520d90480c 100644 --- a/src/doc/reference/src/types/closure.md +++ b/src/doc/reference/src/types/closure.md @@ -22,13 +22,15 @@ f(|| { generates a closure type roughly like the following: + ```rust,ignore struct Closure<'a> { s : String, t : &'a String, } -impl<'a> (FnOnce() -> String) for Closure<'a> { +impl<'a> FnOnce<()> for Closure<'a> { + type Output = String; fn call_once(self) -> String { self.s += &*self.t; self.s @@ -38,6 +40,7 @@ impl<'a> (FnOnce() -> String) for Closure<'a> { so that the call to `f` works as if it were: + ```rust,ignore f(Closure{s: s, t: &t}); ``` diff --git a/src/doc/reference/src/types/inferred.md b/src/doc/reference/src/types/inferred.md index 0100758b21..c754f310b7 100644 --- a/src/doc/reference/src/types/inferred.md +++ b/src/doc/reference/src/types/inferred.md @@ -13,6 +13,6 @@ let x: Vec<_> = (0..10).collect(); diff --git a/src/doc/reference/src/types/never.md b/src/doc/reference/src/types/never.md index 57096ea83e..80105b1cd6 100644 --- a/src/doc/reference/src/types/never.md +++ b/src/doc/reference/src/types/never.md @@ -6,3 +6,17 @@ The never type `!` is a type with no values, representing the result of computations that never complete. Expressions of type `!` can be coerced into any other type. + +```rust,should_panic +#![feature(never_type)] +let x: ! = panic!(); +// Can be coerced into any type. +let y: u32 = x; +``` + +**NB.** The never type was expected to be stabilized in 1.41, but due +to some last minute regressions detected the stabilization was +temporarily reverted. The `!` type can only appear in function return +types presently. See [the tracking +issue](https://github.com/rust-lang/rust/issues/35121) for more +details. diff --git a/src/doc/rust-by-example/src/crates.md b/src/doc/rust-by-example/src/crates.md index 4c46e553cd..b954eec6cd 100644 --- a/src/doc/rust-by-example/src/crates.md +++ b/src/doc/rust-by-example/src/crates.md @@ -9,4 +9,4 @@ individually, only crates get compiled. A crate can be compiled into a binary or into a library. By default, `rustc` will produce a binary from a crate. This behavior can be overridden by passing -the `--crate-type` flag to `rustc`. +the `--crate-type` flag to `lib`. diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md b/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md index 793673f8df..d2273f698f 100644 --- a/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md +++ b/src/doc/rust-by-example/src/error/multiple_error_types/option_result.md @@ -39,9 +39,7 @@ fn double_first(vec: Vec<&str>) -> Result, ParseIntError> { first.parse::().map(|n| 2 * n) }); - let opt = opt.map_or(Ok(None), |r| r.map(Some))?; - - Ok(opt) + opt.map_or(Ok(None), |r| r.map(Some)) } fn main() { diff --git a/src/doc/rustc-guide/.travis.yml b/src/doc/rustc-guide/.travis.yml index c33c38b84f..6ee759d4cc 100644 --- a/src/doc/rustc-guide/.travis.yml +++ b/src/doc/rustc-guide/.travis.yml @@ -4,7 +4,7 @@ rust: cache: - cargo - directories: - - $HOME/linkcheck/ + - book/linkcheck/ before_install: - shopt -s globstar - MAX_LINE_LENGTH=100 bash ci/check_line_lengths.sh src/**/*.md @@ -12,8 +12,7 @@ install: - source ~/.cargo/env || true - bash -x ci/install.sh script: -- bash -x ci/build-ignore-timeouts.sh -- mdbook test +- mdbook build notifications: email: on_success: never diff --git a/src/doc/rustc-guide/README.md b/src/doc/rustc-guide/README.md index 064f80c6e4..12d46b4e52 100644 --- a/src/doc/rustc-guide/README.md +++ b/src/doc/rustc-guide/README.md @@ -1,3 +1,6 @@ +![Travis CI badge](https://api.travis-ci.com/rust-lang/rustc-guide.svg?branch=master) + + This is a collaborative effort to build a guide that explains how rustc works. The aim of the guide is to help new contributors get oriented to rustc, as well as to help more experienced folks in figuring out @@ -41,3 +44,42 @@ be found. You will need `mdbook` version `>= 0.2`. `linkcheck` will be run automatically when you run `mdbook build`. + +## How to fix toolstate failures + +1. You will get a ping from the toolstate commit. e.g. https://github.com/rust-lang-nursery/rust-toolstate/commit/8ffa0e4c30ac9ba8546b7046e5c4ccc2b96ebdd4 + +2. The commit contains a link to the PR that caused the breakage. e.g. https://github.com/rust-lang/rust/pull/64321 + +3. If you go to that PR's thread, there is a post from bors with a link to the CI status: https://github.com/rust-lang/rust/pull/64321#issuecomment-529763807 + +4. Follow the check-azure link to get to the Azure website for that build: https://dev.azure.com/rust-lang/e71b0ddf-dd27-435a-873c-e30f86eea377/_build/results?buildId=7780 + +5. There will be approximately 1 billion different jobs for the build. They are for different configurations and platforms. The rustc-guide build only runs on the Linux x86_64-gnu-tools job. So click on that job in the list, which is about 60% down in the list. + +6. Click the Run build step in the job to get the console log for the step. + +7. Click on the log and Ctrl-f to get a search box in the log + +8. Search for rustc-guide. This gets you to the place where the links are checked. It is usually ~11K lines into the log + +9. Look at the links in the log near that point in the log + +10. Fix those links in the rustc-guide (by making a PR in the rustc-guide repo) + +11. Make a PR on the rust-lang/rust repo to update the rustc-guide git submodule in src/docs/rustc-guide. +To make a PR, the following steps are useful. + +```bash +# Assuming you already cloned the rust-lang/rust repo and you're in the correct directory +git submodule update --remote src/doc/rustc-guide +git add -u +git commit -m "Update rustc-guide" +# Note that you can use -i, which is short for --incremental, in the following command +./x.py test --incremental --stage 1 src/doc/rustc-guide # This is optional and should succeed anyway +# Open a PR in rust-lang/rust +``` + +12. Wait for PR to merge + +Voila! diff --git a/src/doc/rustc-guide/book.toml b/src/doc/rustc-guide/book.toml index 1d207bf22a..bbba6d60ce 100644 --- a/src/doc/rustc-guide/book.toml +++ b/src/doc/rustc-guide/book.toml @@ -7,10 +7,14 @@ description = "A guide to developing rustc" create-missing = false [output.html] +git-repository-url = "https://github.com/rust-lang/rustc-guide" -[output.html.search] +[output.html.fold] +enable = true +level = 1 [output.linkcheck] -command = "sed 's/.*//'" # tell mdbook not to run, since we want to run it manually follow-web-links = true -exclude = [ "crates\\.io", "gcc\\.godbolt\\.org", "youtube\\.com", "dl\\.acm\\.org" ] +exclude = [ "crates\\.io", "gcc\\.godbolt\\.org", "youtube\\.com", "youtu\\.be", "dl\\.acm\\.org" ] +cache-timeout = 172800 +warning-policy = "error" diff --git a/src/doc/rustc-guide/ci/build-ignore-timeouts.sh b/src/doc/rustc-guide/ci/build-ignore-timeouts.sh deleted file mode 100755 index 3ec81f6245..0000000000 --- a/src/doc/rustc-guide/ci/build-ignore-timeouts.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -x - -output=$(mktemp) - -mkdir -p book/ -cp -r $HOME/linkcheck/ book/ -RUST_LOG=mdbook_linkcheck=debug mdbook-linkcheck -s 2>&1 | tee -a $output -cp -r book/linkcheck $HOME/ - -mdbook build - -result=${PIPESTATUS[0]} - -# if passed, great! -if [ "$result" -eq "0" ] ; then - exit 0 ; -fi - -errors=$(cat $output | sed -n 's/There \(was\|were\) \([0-9]\+\).*$/\2/p') -timeouts=$(cat $output | grep "error while fetching" | wc -l) - -# if all errors are timeouts, ignore them... -if [ "$errors" -eq "$timeouts" ] ; then - echo "Ignoring $timeouts timeouts"; - exit 0; -else - echo "Non-timeout errors found"; - exit 1; -fi diff --git a/src/doc/rustc-guide/ci/install.sh b/src/doc/rustc-guide/ci/install.sh index a81e21c561..5cb2f41fca 100755 --- a/src/doc/rustc-guide/ci/install.sh +++ b/src/doc/rustc-guide/ci/install.sh @@ -20,5 +20,5 @@ function cargo_install() { fi } -cargo_install mdbook 0.3.1 -cargo_install mdbook-linkcheck 0.4.0 +cargo_install mdbook 0.3.4 +cargo_install mdbook-linkcheck 0.5.0 diff --git a/src/doc/rustc-guide/src/SUMMARY.md b/src/doc/rustc-guide/src/SUMMARY.md index f672df5101..fe6584b554 100644 --- a/src/doc/rustc-guide/src/SUMMARY.md +++ b/src/doc/rustc-guide/src/SUMMARY.md @@ -6,9 +6,12 @@ - [Part 1: Building, debugging, and contributing to Rustc](./part-1-intro.md) - [About the compiler team](./compiler-team.md) - - [How to Build and Run the Compiler](./how-to-build-and-run.md) - - [Build and Install distribution artifacts](./build-install-distribution-artifacts.md) - - [Documenting Compiler](./compiler-documenting.md) + - [How to Build and Run the Compiler](./building/how-to-build-and-run.md) + - [Suggested Workflows](./building/suggested.md) + - [Bootstrapping](./building/bootstrapping.md) + - [Distribution artifacts](./building/build-install-distribution-artifacts.md) + - [Documenting Compiler](./building/compiler-documenting.md) + - [ctags](./building/ctags.md) - [The compiler testing framework](./tests/intro.md) - [Running tests](./tests/running.md) - [Adding new tests](./tests/adding.md) @@ -23,7 +26,9 @@ - [Coding conventions](./conventions.md) - [crates.io Dependencies](./crates-io.md) - [Emitting Errors and other Diagnostics](diagnostics.md) - - [JSON diagnostic format](diagnostics/json-format.md) + - [`LintStore`](./diagnostics/lintstore.md) + - [ICE-breaker teams](ice-breaker/about.md) + - [LLVM ICE-breakers](ice-breaker/llvm.md) - [Part 2: How rustc works](./part-2-intro.md) - [High-level overview of the compiler source](./high-level-overview.md) - [The Rustc Driver and Interface](./rustc-driver.md) @@ -33,7 +38,8 @@ - [Incremental compilation](./queries/incremental-compilation.md) - [Incremental compilation In Detail](./queries/incremental-compilation-in-detail.md) - [Debugging and Testing](./incrcomp-debugging.md) - - [The parser](./the-parser.md) + - [Salsa](./salsa.md) + - [Lexing and Parsing](./the-parser.md) - [`#[test]` Implementation](./test-implementation.md) - [Macro expansion](./macro-expansion.md) - [Name resolution](./name-resolution.md) @@ -42,7 +48,7 @@ - [Debugging](./hir-debugging.md) - [Closure expansion](./closure.md) - [The `ty` module: representing types](./ty.md) - - [Kinds](./kinds.md) + - [Generic arguments](./generic_arguments.md) - [Type inference](./type-inference.md) - [Trait solving (old-style)](./traits/resolution.md) - [Higher-ranked trait bounds](./traits/hrtb.md) @@ -90,7 +96,9 @@ - [Code Generation](./codegen.md) - [Updating LLVM](./codegen/updating-llvm.md) - [Debugging LLVM](./codegen/debugging.md) + - [Backend Agnostic Codegen](./codegen/backend-agnostic.md) - [Profile-guided Optimization](./profile-guided-optimization.md) + - [Sanitizers Support](./sanitizers.md) - [Debugging Support in Rust Compiler](./debugging-support-in-rustc.md) --- @@ -99,12 +107,11 @@ [Appendix B: Background material](./appendix/background.md) [Appendix C: Glossary](./appendix/glossary.md) [Appendix D: Code Index](./appendix/code-index.md) -[Appendix E: Bibliography](./appendix/bibliography.md) +[Appendix E: Compiler Lecture Series](./appendix/compiler-lecture.md) +[Appendix F: Bibliography](./appendix/bibliography.md) [Appendix Z: HumorRust](./appendix/humorust.md) --- -[](./important-links.md) - [pau]: ./borrow_check/region_inference/placeholders_and_universes.md diff --git a/src/doc/rustc-guide/src/appendix/background.md b/src/doc/rustc-guide/src/appendix/background.md index dbfe6a3dbe..50a550dc8d 100644 --- a/src/doc/rustc-guide/src/appendix/background.md +++ b/src/doc/rustc-guide/src/appendix/background.md @@ -126,3 +126,38 @@ So what does this have to do with regions? Well, we can apply the analogous concept to type and regions. For example, in the type `&'a u32`, `'a` appears free. But in the type `for<'a> fn(&'a u32)`, it does not. + +# Further Reading About Compilers + +> Thanks to `mem`, `scottmcm`, and `Levi` on the official Discord for the +> recommendations, and to `tinaun` for posting a link to a [twitter thread from +> Graydon Hoare](https://twitter.com/graydon_pub/status/1039615569132118016) +> which had some more recommendations! +> +> Other sources: https://gcc.gnu.org/wiki/ListOfCompilerBooks +> +> If you have other suggestions, please feel free to open an issue or PR. + +## Books +- [Types and Programming Languages](https://www.cis.upenn.edu/~bcpierce/tapl/) +- [Programming Language Pragmatics](https://www.cs.rochester.edu/~scott/pragmatics/) +- [Practical Foundations for Programming Languages](https://www.cs.cmu.edu/~rwh/pfpl/2nded.pdf) +- [Compilers: Principles, Techniques, and Tools, 2nd Edition](https://www.amazon.com/dp/9332518661/ref=cm_sw_r_other_apa_1tUSBb5VHAVA1) +- [Garbage Collection: Algorithms for Automatic Dynamic Memory Management](https://www.cs.kent.ac.uk/people/staff/rej/gcbook/) +- [Linkers and Loaders](https://linker.iecc.com/) +- [Advanced Compiler Design and Implementation](https://www.goodreads.com/book/show/887908.Advanced_Compiler_Design_and_Implementation) +- [Building an Optimizing Compiler](https://www.goodreads.com/book/show/2063103.Building_an_Optimizing_Compiler) +- [Crafting Interpreters](http://www.craftinginterpreters.com/) + +## Courses +- [University of Oregon Programming Languages Summer School archive](https://www.cs.uoregon.edu/research/summerschool/archives.html) + +## Wikis +- [Wikipedia](https://en.wikipedia.org/wiki/List_of_programming_languages_by_type) +- [Esoteric Programming Languages](https://esolangs.org/wiki/Main_Page) +- [Stanford Encyclopedia of Philosophy](https://plato.stanford.edu/index.html) +- [nLab](https://ncatlab.org/nlab/show/HomePage) + +## Misc Papers and Blog Posts +- [Programming in Martin-Löf's Type Theory](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.118.6683&rep=rep1&type=pdf) +- [Polymorphism, Subtyping, and Type Inference in MLsub](https://www.cl.cam.ac.uk/~sd601/papers/mlsub-preprint.pdf) diff --git a/src/doc/rustc-guide/src/appendix/bibliography.md b/src/doc/rustc-guide/src/appendix/bibliography.md index 03ba3a41ce..c3d0446c76 100644 --- a/src/doc/rustc-guide/src/appendix/bibliography.md +++ b/src/doc/rustc-guide/src/appendix/bibliography.md @@ -31,7 +31,7 @@ Rust, as well as publications about Rust. * [Balanced work stealing for time-sharing multicores](http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/papers/TR-12-1.pdf) * [Three layer cake for shared-memory programming](http://dl.acm.org/citation.cfm?id=1953616&dl=ACM&coll=DL&CFID=524387192&CFTOKEN=44362705) * [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf) -* [Reagents: expressing and composing fine-grained concurrency](http://aturon.github.io/academic/reagents.pdf) +* [Reagents: expressing and composing fine-grained concurrency](https://aturon.github.io/academic/reagents.pdf) * [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf) * [Epoch-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf). @@ -59,7 +59,7 @@ Rust, as well as publications about Rust. Rust](https://michaelsproul.github.io/rust_radix_paper/rust-radix-sproul.pdf). Undergrad paper by Michael Sproul. * [Reenix: Implementing a Unix-Like Operating System in - Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex + Rust](https://scialex.github.io/reenix.pdf). Undergrad paper by Alex Light. * [Evaluation of performance and productivity metrics of potential programming languages in the HPC environment](https://github.com/1wilkens/thesis-ba). Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust. diff --git a/src/doc/rustc-guide/src/appendix/code-index.md b/src/doc/rustc-guide/src/appendix/code-index.md index 267a3a3ea5..1c8d1d7076 100644 --- a/src/doc/rustc-guide/src/appendix/code-index.md +++ b/src/doc/rustc-guide/src/appendix/code-index.md @@ -17,14 +17,14 @@ Item | Kind | Short description | Chapter | `NodeId` | struct | One of four types of HIR node identifiers. Being phased out | [Identifiers in the HIR] | [src/libsyntax/ast.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/struct.NodeId.html) `P` | struct | An owned immutable smart pointer. By contrast, `&T` is not owned, and `Box` is not immutable. | None | [src/syntax/ptr.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ptr/struct.P.html) `ParamEnv` | struct | Information about generic parameters or `Self`, useful for working with associated or generic items | [Parameter Environment] | [src/librustc/ty/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.ParamEnv.html) -`ParseSess` | struct | This struct contains information about a parsing session | [The parser] | [src/libsyntax/parse/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/struct.ParseSess.html) +`ParseSess` | struct | This struct contains information about a parsing session | [The parser] | [src/libsyntax/parse/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/sess/struct.ParseSess.html) `Query` | struct | Represents the result of query to the `Compiler` interface and allows stealing, borrowing, and returning the results of compiler passes. | [The Rustc Driver and Interface] | [src/librustc_interface/queries.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/queries/struct.Query.html) `Rib` | struct | Represents a single scope of names | [Name resolution] | [src/librustc_resolve/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.Rib.html) -`Session` | struct | The data associated with a compilation session | [The parser], [The Rustc Driver and Interface] | [src/librustc/session/mod.html](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html) +`Session` | struct | The data associated with a compilation session | [The parser], [The Rustc Driver and Interface] | [src/librustc/session/mod.html](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html) `SourceFile` | struct | Part of the `SourceMap`. Maps AST nodes to their source code for a single source file. Was previously called FileMap | [The parser] | [src/libsyntax_pos/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceFile.html) `SourceMap` | struct | Maps AST nodes to their source code. It is composed of `SourceFile`s. Was previously called CodeMap | [The parser] | [src/libsyntax/source_map.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html) `Span` | struct | A location in the user's source code, used for error reporting primarily | [Emitting Diagnostics] | [src/libsyntax_pos/span_encoding.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax_pos/struct.Span.html) -`StringReader` | struct | This is the lexer used during parsing. It consumes characters from the raw source code being compiled and produces a series of tokens for use by the rest of the parser | [The parser] | [src/libsyntax/parse/lexer/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/lexer/struct.StringReader.html) +`StringReader` | struct | This is the lexer used during parsing. It consumes characters from the raw source code being compiled and produces a series of tokens for use by the rest of the parser | [The parser] | [src/librustc_parse/lexer/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.StringReader.html) `syntax::token_stream::TokenStream` | struct | An abstract sequence of tokens, organized into `TokenTree`s | [The parser], [Macro expansion] | [src/libsyntax/tokenstream.rs](https://doc.rust-lang.org/nightly/nightly-rustc/syntax/tokenstream/struct.TokenStream.html) `TraitDef` | struct | This struct contains a trait's definition with type information | [The `ty` modules] | [src/librustc/ty/trait_def.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/trait_def/struct.TraitDef.html) `TraitRef` | struct | The combination of a trait and its input types (e.g. `P0: Trait`) | [Trait Solving: Goals and Clauses], [Trait Solving: Lowering impls] | [src/librustc/ty/sty.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TraitRef.html) diff --git a/src/doc/rustc-guide/src/appendix/compiler-lecture.md b/src/doc/rustc-guide/src/appendix/compiler-lecture.md new file mode 100644 index 0000000000..3912bab767 --- /dev/null +++ b/src/doc/rustc-guide/src/appendix/compiler-lecture.md @@ -0,0 +1,51 @@ +# Compiler Lecture Series + +These are videos where various experts explain different parts of the compiler: + +- Tom Tromey discusses debugging support in rustc + - Video: https://www.youtube.com/watch?v=elBxMRSNYr4 +- How Salsa Works (2019.01) + - Video: https://www.youtube.com/watch?v=_muY4HjSqVw +- Salsa In More Depth (2019.01) + - Video: https://www.youtube.com/watch?v=i_IhACacPRY +- RLS 2.0, Salsa, and Name Resolution + - Video: https://www.youtube.com/watch?v=Xr-rBqLr-G4 +- Cranelift + - Video: https://www.youtube.com/watch?v=9OIA7DTFQWU +- Rust analyzer guide + - Video: https://www.youtube.com/watch?v=ANKBNiSWyfc +- Rust analyzer syntax trees + - Video: https://www.youtube.com/watch?v=DGAuLWdCCAI +- rust-analyzer type-checker overview by flodiebold + - Video: https://www.youtube.com/watch?v=Lmp3P9WNL8o +- oli-obk on miri and constant evaluation + - Video: https://www.youtube.com/watch?v=5Pm2C1YXrvM +- Polonius-rustc walkthrough + - Video: https://www.youtube.com/watch?v=i5KdU0ieb_A +- rustc-chalk integration overview + - Video: https://www.youtube.com/watch?v=MBWtbDifPeU +- Coherence in Chalk by Sunjay Varma - Bay Area Rust Meetup + - assigned to @juanbono + - Video: https://www.youtube.com/watch?v=rZqS4bLPL24 +- How the chalk-engine crate works + - Video: https://www.youtube.com/watch?v=Ny2928cGDoM +- How the chalk-engine crate works 2 + - Video: https://www.youtube.com/watch?v=hmV66tB79LM +- RFC #2229 Disjoint Field Capture plan + - Video: https://www.youtube.com/watch?v=UTXOptVMuIc +- closures and upvar capture + - Video: https://www.youtube.com/watch?v=fMopdkn5-Xw +- blitzerr closure upvar tys + - Video: https://www.youtube.com/watch?v=pLmVhSB-z4s +- Convert Closure Upvar Representation to Tuples with blitzerr + - Video: https://www.youtube.com/watch?v=2QCuNtISoYc +- async-await implementation plans + - Video: https://www.youtube.com/watch?v=xe2_whJWBC0 +- async-await region inferencer + - Video: https://www.youtube.com/watch?v=hlOxfkUDLPQ +- Universes and Lifetimes + - Video: https://www.youtube.com/watch?v=iV1Z0xYXkck +- Representing types in rustc + - Video: https://www.youtube.com/watch?v=c01TsOsr3-c +- Polonius WG: Initialization and move tracking + - Video: https://www.youtube.com/watch?v=ilv9V-328HI diff --git a/src/doc/rustc-guide/src/appendix/glossary.md b/src/doc/rustc-guide/src/appendix/glossary.md index 3375d035f7..a773e35215 100644 --- a/src/doc/rustc-guide/src/appendix/glossary.md +++ b/src/doc/rustc-guide/src/appendix/glossary.md @@ -10,7 +10,7 @@ AST | the abstract syntax tree produced by the syntax crate binder | a "binder" is a place where a variable or type is declared; for example, the `` is a binder for the generic type parameter `T` in `fn foo(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.html#free-vs-bound) bound variable | a "bound variable" is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.html#free-vs-bound) codegen | the code to translate MIR into LLVM IR. -codegen unit | when we produce LLVM IR, we group the Rust code into a number of codegen units. Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. +codegen unit | when we produce LLVM IR, we group the Rust code into a number of codegen units (sometimes abbreviated as CGUs). Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. completeness | completeness is a technical term in type theory. Completeness means that every type-safe program also type-checks. Having both soundness and completeness is very hard, and usually soundness is more important. (see "soundness"). control-flow graph | a representation of the control-flow of a program; see [the background chapter for more](./background.html#cfg) CTFE | Compile-Time Function Evaluation. This is the ability of the compiler to evaluate `const fn`s at compile time. This is part of the compiler's constant evaluation system. ([see more](../const-eval.html)) @@ -45,6 +45,7 @@ LTO | Link-Time Optimizations. A set of optimizations offer memoize | memoization is the process of storing the results of (pure) computations (such as pure function calls) to avoid having to repeat them in the future. This is typically a trade-off between execution speed and memory usage. MIR | the Mid-level IR that is created after type-checking for use by borrowck and codegen ([see more](../mir/index.html)) miri | an interpreter for MIR used for constant evaluation ([see more](../miri.html)) +monomorphize | Monomorphization is the process of taking generic implementations of types and functions and instantiating them with concrete types. For example, in the code we might have `Vec`, but in the final executable, we will have a copy of the `Vec` code for every concrete type used in the program (e.g. a copy for `Vec`, a copy for `Vec`, etc). normalize | a general term for converting to a more canonical form, but in the case of rustc typically refers to [associated type normalization](../traits/associated-types.html#normalize) newtype | a "newtype" is a wrapper around some other type (e.g., `struct Foo(T)` is a "newtype" for `T`). This is commonly used in Rust to give a stronger type for indices. NLL | [non-lexical lifetimes](../borrow_check/region_inference.html), an extension to Rust's borrowing system to make it be based on the control-flow graph. @@ -61,7 +62,7 @@ rib | a data structure in the name resolver that keeps trac sess | the compiler session, which stores global data used throughout compilation side tables | because the AST and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node. sigil | like a keyword but composed entirely of non-alphanumeric tokens. For example, `&` is a sigil for references. -placeholder | **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow_check/region_inference.html#placeholders-and-universes) for more details. +placeholder | **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow_check/region_inference/placeholders_and_universes.md) for more details. soundness | soundness is a technical term in type theory. Roughly, if a type system is sound, then if a program type-checks, it is type-safe; i.e. I can never (in safe rust) force a value into a variable of the wrong type. (see "completeness"). span | a location in the user's source code, used for error reporting primarily. These are like a file-name/line-number/column tuple on steroids: they carry a start/end point, and also track macro expansions and compiler desugaring. All while being packed into a few bytes (really, it's an index into a table). See the Span datatype for more. substs | the substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap`) diff --git a/src/doc/rustc-guide/src/borrow_check.md b/src/doc/rustc-guide/src/borrow_check.md index b3864aac47..0ceb21d72e 100644 --- a/src/doc/rustc-guide/src/borrow_check.md +++ b/src/doc/rustc-guide/src/borrow_check.md @@ -27,7 +27,7 @@ Doing borrow checking on MIR has several advantages: which are regions derived from the control-flow graph. [47366]: https://github.com/rust-lang/rust/issues/47366 -[nll]: http://rust-lang.github.io/rfcs/2094-nll.html +[nll]: https://rust-lang.github.io/rfcs/2094-nll.html ### Major phases of the borrow checker diff --git a/src/doc/rustc-guide/src/borrow_check/moves_and_initialization/move_paths.md b/src/doc/rustc-guide/src/borrow_check/moves_and_initialization/move_paths.md index 157a9eaf3e..9b8cbd47ae 100644 --- a/src/doc/rustc-guide/src/borrow_check/moves_and_initialization/move_paths.md +++ b/src/doc/rustc-guide/src/borrow_check/moves_and_initialization/move_paths.md @@ -88,6 +88,7 @@ If you have a [`Place`] and you would like to convert it to a [`MovePathIndex`], can do that using the [`MovePathLookup`] structure found in the [`rev_lookup`] field of [`MoveData`]. There are two different methods: +[`MoveData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MoveData.html [`MovePathLookup`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePathLookup.html [`rev_lookup`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MoveData.html#structfield.rev_lookup diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference.md b/src/doc/rustc-guide/src/borrow_check/region_inference.md index 216128ffb8..5ae0965743 100644 --- a/src/doc/rustc-guide/src/borrow_check/region_inference.md +++ b/src/doc/rustc-guide/src/borrow_check/region_inference.md @@ -42,7 +42,7 @@ The MIR-based region analysis consists of two major functions: [`compute_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.compute_regions.html [`RegionInferenceContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html [`solve`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/region_infer/struct.RegionInferenceContext.html#method.solve -[NLL RFC]: http://rust-lang.github.io/rfcs/2094-nll.html +[NLL RFC]: https://rust-lang.github.io/rfcs/2094-nll.html [MIR type checker]: ./type_check.md ## Universal regions @@ -100,7 +100,7 @@ The kinds of region elements are as follows: - There is an element `!1` for each placeholder region `!1`. This corresponds (intuitively) to some unknown set of other elements – for details on placeholders, see the section - [placeholders and universes](#placeholder). + [placeholders and universes](region_inference/placeholders_and_universes.md). ## Constraints diff --git a/src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md b/src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md index 7e254f0a25..0435ff8c85 100644 --- a/src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md +++ b/src/doc/rustc-guide/src/borrow_check/region_inference/member_constraints.md @@ -97,7 +97,7 @@ placement of impl Trait, though in the future it may not be the case. We take some advantage of this fact, as it simplifies the current code. In particular, we don't have to consider a case like `'0 member of ['1, 'static]`, in which the value of both `'0` and `'1` are being -inferred and hence changing. See [rust-lang/rust#61773] for more +inferred and hence changing. See [rust-lang/rust#61773][#61773] for more information. [#61773]: https://github.com/rust-lang/rust/issues/61773 diff --git a/src/doc/rustc-guide/src/building/bootstrapping.md b/src/doc/rustc-guide/src/building/bootstrapping.md new file mode 100644 index 0000000000..1265090772 --- /dev/null +++ b/src/doc/rustc-guide/src/building/bootstrapping.md @@ -0,0 +1,161 @@ +# Bootstrapping the Compiler + +This subchapter is about the bootstrapping process. + +When running `x.py` you will see output such as: + +```txt +Building stage0 std artifacts +Copying stage0 std from stage0 +Building stage0 compiler artifacts +Copying stage0 rustc from stage0 +Building LLVM for x86_64-apple-darwin +Building stage0 codegen artifacts +Assembling stage1 compiler +Building stage1 std artifacts +Copying stage1 std from stage1 +Building stage1 compiler artifacts +Copying stage1 rustc from stage1 +Building stage1 codegen artifacts +Assembling stage2 compiler +Uplifting stage1 std +Copying stage2 std from stage1 +Generating unstable book md files +Building stage0 tool unstable-book-gen +Building stage0 tool rustbook +Documenting standalone +Building rustdoc for stage2 +Documenting book redirect pages +Documenting stage2 std +Building rustdoc for stage1 +Documenting stage2 whitelisted compiler +Documenting stage2 compiler +Documenting stage2 rustdoc +Documenting error index +Uplifting stage1 rustc +Copying stage2 rustc from stage1 +Building stage2 tool error_index_generator +``` + +A deeper look into `x.py`'s phases can be seen here: + +A diagram of the rustc compilation phases + +Keep in mind this diagram is a simplification, i.e. `rustdoc` can be built at +different stages, the process is a bit different when passing flags such as +`--keep-stage`, or if there are non-host targets. + +The following tables indicate the outputs of various stage actions: + +| Stage 0 Action | Output | +|-----------------------------------------------------------|----------------------------------------------| +| `beta` extracted | `build/HOST/stage0` | +| `stage0` builds `bootstrap` | `build/bootstrap` | +| `stage0` builds `libstd` | `build/HOST/stage0-std/TARGET` | +| copy `stage0-std` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | +| `stage0` builds `rustc` with `stage0-sysroot` | `build/HOST/stage0-rustc/HOST` | +| copy `stage0-rustc (except executable)` | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | +| build `llvm` | `build/HOST/llvm` | +| `stage0` builds `codegen` with `stage0-sysroot` | `build/HOST/stage0-codegen/HOST` | +| `stage0` builds `rustdoc` with `stage0-sysroot` | `build/HOST/stage0-tools/HOST` | + +`--stage=0` stops here. + +| Stage 1 Action | Output | +|-----------------------------------------------------|---------------------------------------| +| copy (uplift) `stage0-rustc` executable to `stage1` | `build/HOST/stage1/bin` | +| copy (uplift) `stage0-codegen` to `stage1` | `build/HOST/stage1/lib` | +| copy (uplift) `stage0-sysroot` to `stage1` | `build/HOST/stage1/lib` | +| `stage1` builds `libstd` | `build/HOST/stage1-std/TARGET` | +| copy `stage1-std` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` | +| `stage1` builds `rustc` | `build/HOST/stage1-rustc/HOST` | +| copy `stage1-rustc` (except executable) | `build/HOST/stage1/lib/rustlib/HOST` | +| `stage1` builds `codegen` | `build/HOST/stage1-codegen/HOST` | + +`--stage=1` stops here. + +| Stage 2 Action | Output | +|-------------------------------------------|-----------------------------------------------------------------| +| copy (uplift) `stage1-rustc` executable | `build/HOST/stage2/bin` | +| copy (uplift) `stage1-sysroot` | `build/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST` | +| `stage2` builds `libstd` (except HOST?) | `build/HOST/stage2-std/TARGET` | +| copy `stage2-std` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` | +| `stage2` builds `rustdoc` | `build/HOST/stage2-tools/HOST` | +| copy `rustdoc` | `build/HOST/stage2/bin` | + +`--stage=2` stops here. + +Note that the convention `x.py` uses is that: +- A "stage N artifact" is an artifact that is _produced_ by the stage N compiler. +- The "stage (N+1) compiler" is assembled from "stage N artifacts". +- A `--stage N` flag means build _with_ stage N. + +In short, _stage 0 uses the stage0 compiler to create stage0 artifacts which +will later be uplifted to stage1_. + +Every time any of the main artifacts (`std` and `rustc`) are compiled, two +steps are performed. +When `std` is compiled by a stage N compiler, that `std` will be linked to +programs built by the stage N compiler (including `rustc` built later +on). It will also be used by the stage (N+1) compiler to link against itself. +This is somewhat intuitive if one thinks of the stage (N+1) compiler as "just" +another program we are building with the stage N compiler. In some ways, `rustc` +(the binary, not the `rustbuild` step) could be thought of as one of the few +`no_core` binaries out there. + +So "stage0 std artifacts" are in fact the output of the downloaded stage0 +compiler, and are going to be used for anything built by the stage0 compiler: +e.g. `rustc` artifacts. When it announces that it is "building stage1 +std artifacts" it has moved on to the next bootstrapping phase. This pattern +continues in latter stages. + +Also note that building host `std` and target `std` are different based on the +stage (e.g. see in the table how stage2 only builds non-host `std` targets. +This is because during stage2, the host `std` is uplifted from the "stage 1" +`std` -- specifically, when "Building stage 1 artifacts" is announced, it is +later copied into stage2 as well (both the compiler's `libdir` and the +`sysroot`). + +This `std` is pretty much necessary for any useful work with the compiler. +Specifically, it's used as the `std` for programs compiled by the newly compiled +compiler (so when you compile `fn main() { }` it is linked to the last `std` +compiled with `x.py build --stage 1 src/libstd`). + +The `rustc` generated by the stage0 compiler is linked to the freshly-built +`libstd`, which means that for the most part only `std` needs to be cfg-gated, +so that `rustc` can use featured added to std immediately after their addition, +without need for them to get into the downloaded beta. The `libstd` built by the +`stage1/bin/rustc` compiler, also known as "stage1 std artifacts", is not +necessarily ABI-compatible with that compiler. +That is, the `rustc` binary most likely could not use this `std` itself. +It is however ABI-compatible with any programs that the `stage1/bin/rustc` +binary builds (including itself), so in that sense they're paired. + +This is also where `--keep-stage 1 src/libstd` comes into play. Since most +changes to the compiler don't actually change the ABI, once you've produced a +`libstd` in stage 1, you can probably just reuse it with a different compiler. +If the ABI hasn't changed, you're good to go, no need to spend the time +recompiling that `std`. +`--keep-stage` simply assumes the previous compile is fine and copies those +artifacts into the appropriate place, skipping the cargo invocation. + +The reason we first build `std`, then `rustc`, is largely just +because we want to minimize `cfg(stage0)` in the code for `rustc`. +Currently `rustc` is always linked against a "new" `std` so it doesn't +ever need to be concerned with differences in std; it can assume that the std is +as fresh as possible. + +The reason we need to build it twice is because of ABI compatibility. +The beta compiler has it's own ABI, and then the `stage1/bin/rustc` compiler +will produce programs/libraries with the new ABI. +We used to build three times, but because we assume that the ABI is constant +within a codebase, we presume that the libraries produced by the "stage2" +compiler (produced by the `stage1/bin/rustc` compiler) is ABI-compatible with +the `stage1/bin/rustc` compiler's produced libraries. +What this means is that we can skip that final compilation -- and simply use the +same libraries as the `stage2/bin/rustc` compiler uses itself for programs it +links against. + +This `stage2/bin/rustc` compiler is shipped to end-users, along with the +`stage 1 {std,rustc}` artifacts. + diff --git a/src/doc/rustc-guide/src/build-install-distribution-artifacts.md b/src/doc/rustc-guide/src/building/build-install-distribution-artifacts.md similarity index 100% rename from src/doc/rustc-guide/src/build-install-distribution-artifacts.md rename to src/doc/rustc-guide/src/building/build-install-distribution-artifacts.md diff --git a/src/doc/rustc-guide/src/building/compiler-documenting.md b/src/doc/rustc-guide/src/building/compiler-documenting.md new file mode 100644 index 0000000000..16df10f720 --- /dev/null +++ b/src/doc/rustc-guide/src/building/compiler-documenting.md @@ -0,0 +1,52 @@ +# Documenting rustc + +You might want to build documentation of the various components +available like the standard library. There’s two ways to go about this. +You can run rustdoc directly on the file to make sure the HTML is +correct, which is fast. Alternatively, you can build the documentation +as part of the build process through x.py. Both are viable methods +since documentation is more about the content. + +## Document everything + +```bash +./x.py doc +``` + +## If you want to avoid the whole Stage 2 build + +```bash +./x.py doc --stage 1 +``` + +First the compiler and rustdoc get built to make sure everything is okay +and then it documents the files. + +## Document specific components + +```bash +./x.py doc src/doc/book +./x.py doc src/doc/nomicon +./x.py doc src/doc/book src/libstd +``` + +Much like individual tests or building certain components you can build only + the documentation you want. + +## Document internal rustc items + +Compiler documentation is not built by default. To enable it, modify config.toml: + +```toml +[build] +compiler-docs = true +``` + +Note that when enabled, +documentation for internal compiler items will also be built. + +### Compiler Documentation + +The documentation for the rust components are found at [rustc doc]. + +[rustc doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ diff --git a/src/doc/rustc-guide/src/building/ctags.md b/src/doc/rustc-guide/src/building/ctags.md new file mode 100644 index 0000000000..9b63314578 --- /dev/null +++ b/src/doc/rustc-guide/src/building/ctags.md @@ -0,0 +1,26 @@ +# ctags + +One of the challenges with rustc is that the RLS can't handle it, since it's a +bootstrapping compiler. This makes code navigation difficult. One solution is to +use `ctags`. + +`ctags` has a long history and several variants. Exuberant Ctags seems to be +quite commonly distributed but it does not have out-of-box Rust support. Some +distributions seem to use [Universal Ctags][utags], which is a maintained fork +and does have built-in Rust support. + +The following script can be used to set up Exuberant Ctags: +[https://github.com/nikomatsakis/rust-etags][etags]. + +`ctags` integrates into emacs and vim quite easily. The following can then be +used to build and generate tags: + +```console +$ rust-ctags src/lib* && ./x.py build +``` + +This allows you to do "jump-to-def" with whatever functions were around when +you last built, which is ridiculously useful. + +[etags]: https://github.com/nikomatsakis/rust-etags +[utags]: https://github.com/universal-ctags/ctags diff --git a/src/doc/rustc-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-guide/src/building/how-to-build-and-run.md new file mode 100644 index 0000000000..69c418c28d --- /dev/null +++ b/src/doc/rustc-guide/src/building/how-to-build-and-run.md @@ -0,0 +1,277 @@ +# How to Build and Run the Compiler + +The compiler is built using a tool called `x.py`. You will need to +have Python installed to run it. But before we get to that, if you're going to +be hacking on `rustc`, you'll want to tweak the configuration of the compiler. +The default configuration is oriented towards running the compiler as a user, +not a developer. + +## Create a config.toml + +To start, copy [`config.toml.example`] to `config.toml`: + +[`config.toml.example`]: https://github.com/rust-lang/rust/blob/master/config.toml.example + +```bash +> cd $RUST_CHECKOUT +> cp config.toml.example config.toml +``` + +Then you will want to open up the file and change the following +settings (and possibly others, such as `llvm.ccache`): + +```toml +[llvm] +# Enables LLVM assertions, which will check that the LLVM bitcode generated +# by the compiler is internally consistent. These are particularly helpful +# if you edit `codegen`. +assertions = true + +[rust] +# This will make your build more parallel; it costs a bit of runtime +# performance perhaps (less inlining) but it's worth it. +codegen-units = 0 + +# This enables full debuginfo and debug assertions. The line debuginfo is also +# enabled by `debuginfo-level = 1`. Full debuginfo is also enabled by +# `debuginfo-level = 2`. Debug assertions can also be enabled with +# `debug-assertions = true`. Note that `debug = true` will make your build +# slower, so you may want to try individually enabling debuginfo and assertions +# or enable only line debuginfo which is basically free. +debug = true +``` + +If you have already built `rustc`, then you may have to execute `rm -rf build` for subsequent +configuration changes to take effect. Note that `./x.py clean` will not cause a +rebuild of LLVM, so if your configuration change affects LLVM, you will need to +manually `rm -rf build/` before rebuilding. + +## What is `x.py`? + +`x.py` is the script used to orchestrate the tooling in the `rustc` repository. +It is the script that can build docs, run tests, and compile `rustc`. +It is the now preferred way to build `rustc` and it replaces the old makefiles +from before. Below are the different ways to utilize `x.py` in order to +effectively deal with the repo for various common tasks. + +This chapter focuses on the basics to be productive, but +if you want to learn more about `x.py`, read its README.md +[here](https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md). + +## Bootstrapping + +One thing to keep in mind is that `rustc` is a _bootstrapping_ +compiler. That is, since `rustc` is written in Rust, we need to use an +older version of the compiler to compile the newer version. In +particular, the newer version of the compiler and some of the artifacts needed +to build it, such as `libstd` and other tooling, may use some unstable features +internally, requiring a specific version which understands these unstable +features. + +The result is that compiling `rustc` is done in stages: + +- **Stage 0:** the stage0 compiler is usually (you can configure `x.py` to use + something else) the current _beta_ `rustc` compiler and its associated dynamic + libraries (which `x.py` will download for you). This stage0 compiler is then + used only to compile `rustbuild`, `std`, and `rustc`. When compiling + `rustc`, this stage0 compiler uses the freshly compiled `std`. + There are two concepts at play here: a compiler (with its set of dependencies) + and its 'target' or 'object' libraries (`std` and `rustc`). + Both are staged, but in a staggered manner. +- **Stage 1:** the code in your clone (for new version) is then + compiled with the stage0 compiler to produce the stage1 compiler. + However, it was built with an older compiler (stage0), so to + optimize the stage1 compiler we go to next the stage. + - In theory, the stage1 compiler is functionally identical to the + stage2 compiler, but in practice there are subtle differences. In + particular, the stage1 compiler itself was built by stage0 and + hence not by the source in your working directory: this means that + the symbol names used in the compiler source may not match the + symbol names that would have been made by the stage1 compiler. + This can be important when using dynamic linking (e.g., with + derives. Sometimes this means that some tests don't work when run + with stage1. +- **Stage 2:** we rebuild our stage1 compiler with itself to produce + the stage2 compiler (i.e. it builds itself) to have all the _latest + optimizations_. (By default, we copy the stage1 libraries for use by + the stage2 compiler, since they ought to be identical.) +- _(Optional)_ **Stage 3**: to sanity check our new compiler, we + can build the libraries with the stage2 compiler. The result ought + to be identical to before, unless something has broken. + +To read more about the bootstrap process, [read this chapter][bootstrap]. + +[bootstrap]: ./bootstrapping.md + +## Building the Compiler + +To build a compiler, run `./x.py build`. This will do the whole bootstrapping +process described above, producing a usable compiler toolchain from the source +code you have checked out. This takes a long time, so it is not usually what +you want to actually run (more on this later). + +There are many flags you can pass to the build command of `x.py` that can be +beneficial to cutting down compile times or fitting other things you might +need to change. They are: + +```txt +Options: + -v, --verbose use verbose output (-vv for very verbose) + -i, --incremental use incremental compilation + --config FILE TOML configuration file for build + --build BUILD build target of the stage0 compiler + --host HOST host targets to build + --target TARGET target targets to build + --on-fail CMD command to run on failure + --stage N stage to build + --keep-stage N stage to keep without recompiling + --src DIR path to the root of the rust checkout + -j, --jobs JOBS number of jobs to run in parallel + -h, --help print this help message +``` + +For hacking, often building the stage 1 compiler is enough, but for +final testing and release, the stage 2 compiler is used. + +`./x.py check` is really fast to build the rust compiler. +It is, in particular, very useful when you're doing some kind of +"type-based refactoring", like renaming a method, or changing the +signature of some function. + + + +Once you've created a config.toml, you are now ready to run +`x.py`. There are a lot of options here, but let's start with what is +probably the best "go to" command for building a local rust: + +```bash +./x.py build -i --stage 1 src/libstd +``` + +This may *look* like it only builds libstd, but that is not the case. +What this command does is the following: + +- Build `libstd` using the stage0 compiler (using incremental) +- Build `librustc` using the stage0 compiler (using incremental) + - This produces the stage1 compiler +- Build libstd using the stage1 compiler (cannot use incremental) + +This final product (stage1 compiler + libs built using that compiler) +is what you need to build other rust programs (unless you use `#![no_std]` or +`#![no_core]`). + +The command includes the `-i` switch which enables incremental compilation. +This will be used to speed up the first two steps of the process: +in particular, if you make a small change, we ought to be able to use your old +results to make producing the stage1 **compiler** faster. + +Unfortunately, incremental cannot be used to speed up making the +stage1 libraries. This is because incremental only works when you run +the *same compiler* twice in a row. In this case, we are building a +*new stage1 compiler* every time. Therefore, the old incremental +results may not apply. **As a result, you will probably find that +building the stage1 `libstd` is a bottleneck for you** -- but fear not, +there is a (hacky) workaround. See [the section on "recommended +workflows"](./suggested.md) below. + +Note that this whole command just gives you a subset of the full `rustc` +build. The **full** `rustc` build (what you get if you just say `./x.py +build`) has quite a few more steps: + +- Build `librustc` and `rustc` with the stage1 compiler. + - The resulting compiler here is called the "stage2" compiler. +- Build libstd with stage2 compiler. +- Build librustdoc and a bunch of other things with the stage2 compiler. + + + +## Build specific components + +Build only the libcore library + +```bash +./x.py build src/libcore +``` + +Build the libcore and libproc_macro library only + +```bash +./x.py build src/libcore src/libproc_macro +``` + +Build only libcore up to Stage 1 + +```bash +./x.py build src/libcore --stage 1 +``` + +Sometimes you might just want to test if the part you’re working on can +compile. Using these commands you can test that it compiles before doing +a bigger build to make sure it works with the compiler. As shown before +you can also pass flags at the end such as --stage. + +## Creating a rustup toolchain + +Once you have successfully built `rustc`, you will have created a bunch +of files in your `build` directory. In order to actually run the +resulting `rustc`, we recommend creating rustup toolchains. The first +one will run the stage1 compiler (which we built above). The second +will execute the stage2 compiler (which we did not build, but which +you will likely need to build at some point; for example, if you want +to run the entire test suite). + +```bash +rustup toolchain link stage1 build//stage1 +rustup toolchain link stage2 build//stage2 +``` + +The `` would typically be one of the following: + +- Linux: `x86_64-unknown-linux-gnu` +- Mac: `x86_64-apple-darwin` +- Windows: `x86_64-pc-windows-msvc` + +Now you can run the `rustc` you built with. If you run with `-vV`, you +should see a version number ending in `-dev`, indicating a build from +your local environment: + +```bash +$ rustc +stage1 -vV +rustc 1.25.0-dev +binary: rustc +commit-hash: unknown +commit-date: unknown +host: x86_64-unknown-linux-gnu +release: 1.25.0-dev +LLVM version: 4.0 +``` +## Other `x.py` commands + +Here are a few other useful `x.py` commands. We'll cover some of them in detail +in other sections: + +- Building things: + - `./x.py clean` – clean up the build directory (`rm -rf build` works too, + but then you have to rebuild LLVM) + - `./x.py build --stage 1` – builds everything using the stage 1 compiler, + not just up to libstd + - `./x.py build` – builds the stage2 compiler +- Running tests (see the [section on running tests](../tests/running.html) for + more details): + - `./x.py test --stage 1 src/libstd` – runs the `#[test]` tests from libstd + - `./x.py test --stage 1 src/test/ui` – runs the `ui` test suite + - `./x.py test --stage 1 src/test/ui/const-generics` - runs all the tests in + the `const-generics/` subdirectory of the `ui` test suite + - `./x.py test --stage 1 src/test/ui/const-generics/const-types.rs` - runs + the single test `const-types.rs` from the `ui` test suite + +### Cleaning out build directories + +Sometimes you need to start fresh, but this is normally not the case. +If you need to run this then rustbuild is most likely not acting right and +you should file a bug as to what is going wrong. If you do need to clean +everything up then you only need to run one command! + +```bash +./x.py clean +``` diff --git a/src/doc/rustc-guide/src/building/suggested.md b/src/doc/rustc-guide/src/building/suggested.md new file mode 100644 index 0000000000..07f834eacd --- /dev/null +++ b/src/doc/rustc-guide/src/building/suggested.md @@ -0,0 +1,78 @@ +# Suggested Workflows + +The full bootstrapping process takes quite a while. Here are three suggestions +to make your life easier. + +## Check, check, and check again + +The first workflow, which is useful +when doing simple refactorings, is to run `./x.py check` +continuously. Here you are just checking that the compiler can +**build**, but often that is all you need (e.g., when renaming a +method). You can then run `./x.py build` when you actually need to +run tests. + +In fact, it is sometimes useful to put off tests even when you are not +100% sure the code will work. You can then keep building up +refactoring commits and only run the tests at some later time. You can +then use `git bisect` to track down **precisely** which commit caused +the problem. A nice side-effect of this style is that you are left +with a fairly fine-grained set of commits at the end, all of which +build and pass tests. This often helps reviewing. + +## Incremental builds with `--keep-stage`. + +Sometimes just checking +whether the compiler builds is not enough. A common example is that +you need to add a `debug!` statement to inspect the value of some +state or better understand the problem. In that case, you really need +a full build. By leveraging incremental, though, you can often get +these builds to complete very fast (e.g., around 30 seconds). The only +catch is this requires a bit of fudging and may produce compilers that +don't work (but that is easily detected and fixed). + +The sequence of commands you want is as follows: + +- Initial build: `./x.py build -i --stage 1 src/libstd` + - As [documented above](#command), this will build a functional + stage1 compiler as part of running all stage0 commands (which include + building a `libstd` compatible with the stage1 compiler) as well as the + first few steps of the "stage 1 actions" up to "stage1 (sysroot stage1) + builds libstd". +- Subsequent builds: `./x.py build -i --stage 1 src/libstd --keep-stage 1` + - Note that we added the `--keep-stage 1` flag here + +As mentioned, the effect of `--keep-stage 1` is that we just *assume* that the +old standard library can be re-used. If you are editing the compiler, this +is almost always true: you haven't changed the standard library, after +all. But sometimes, it's not true: for example, if you are editing +the "metadata" part of the compiler, which controls how the compiler +encodes types and other states into the `rlib` files, or if you are +editing things that wind up in the metadata (such as the definition of +the MIR). + +**The TL;DR is that you might get weird behavior from a compile when +using `--keep-stage 1`** -- for example, strange +[ICEs](../appendix/glossary.html) or other panics. In that case, you +should simply remove the `--keep-stage 1` from the command and +rebuild. That ought to fix the problem. + +You can also use `--keep-stage 1` when running tests. Something like this: + +- Initial test run: `./x.py test -i --stage 1 src/test/ui` +- Subsequent test run: `./x.py test -i --stage 1 src/test/ui --keep-stage 1` + +## Building with system LLVM + +By default, LLVM is built from source, and that can take significant amount of +time. An alternative is to use LLVM already installed on your computer. + +This is specified in the `target` section of `config.toml`: + +```toml +[target.x86_64-unknown-linux-gnu] +llvm-config = "/path/to/llvm/llvm-7.0.1/bin/llvm-config" +``` + +On my system, this path is `/usr/bin/llvm-config-7`, but this probably varies +by installation. diff --git a/src/doc/rustc-guide/src/closure.md b/src/doc/rustc-guide/src/closure.md index c47ad9bc8a..deeed07221 100644 --- a/src/doc/rustc-guide/src/closure.md +++ b/src/doc/rustc-guide/src/closure.md @@ -160,10 +160,10 @@ The other option is to step through the code using lldb or gdb. 2. `r` // Run the program until it hits the breakpoint Let's start with [`upvar.rs`][upvar]. This file has something called -the [`euv::ExprUseVisitor`][euv] which walks the source of the closure and +the [`euv::ExprUseVisitor`] which walks the source of the closure and invokes a callbackfor each upvar that is borrowed, mutated, or moved. -[euv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/middle/expr_use_visitor/struct.ExprUseVisitor.html +[`euv::ExprUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/expr_use_visitor/struct.ExprUseVisitor.html ```rust fn main() { @@ -178,7 +178,7 @@ fn main() { In the above example, our visitor will be called twice, for the lines marked 1 and 2, once for a shared borrow and another one for a mutable borrow. It will also tell us what was borrowed. -The callbacks are defined by implementing the [`Delegate`][delegate] trait. The +The callbacks are defined by implementing the [`Delegate`] trait. The [`InferBorrowKind`][ibk] type implements `Delegate` and keeps a map that records for each upvar which mode of borrow was required. The modes of borrow can be `ByValue` (moved) or `ByRef` (borrowed). For `ByRef` borrows, it can be @@ -208,6 +208,6 @@ self.tables .extend(delegate.adjust_upvar_captures); ``` -[delegate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/middle/expr_use_visitor/trait.Delegate.html +[`Delegate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/expr_use_visitor/trait.Delegate.html [ibk]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/upvar/struct.InferBorrowKind.html -[cmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/middle/mem_categorization/index.html +[cmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/mem_categorization/index.html diff --git a/src/doc/rustc-guide/src/codegen/backend-agnostic.md b/src/doc/rustc-guide/src/codegen/backend-agnostic.md new file mode 100644 index 0000000000..3bf1bde83c --- /dev/null +++ b/src/doc/rustc-guide/src/codegen/backend-agnostic.md @@ -0,0 +1,205 @@ +# Backend Agnostic Codegen + +In the future, it would be nice to allow other codegen backends (e.g. +[Cranelift][cranelift]). To this end, `librustc_codegen_ssa` provides an +abstract interface for all backends to implenent. + +[cranelift]: https://github.com/CraneStation/cranelift + +> The following is a copy/paste of a README from the rust-lang/rust repo. +> Please submit a PR if it needs updating. + +# Refactoring of `rustc_codegen_llvm` +by Denis Merigoux, October 23rd 2018 + +## State of the code before the refactoring + +All the code related to the compilation of MIR into LLVM IR was contained +inside the `rustc_codegen_llvm` crate. Here is the breakdown of the most +important elements: +* the `back` folder (7,800 LOC) implements the mechanisms for creating the + different object files and archive through LLVM, but also the communication + mechanisms for parallel code generation; +* the `debuginfo` (3,200 LOC) folder contains all code that passes debug + information down to LLVM; +* the `llvm` (2,200 LOC) folder defines the FFI necessary to communicate with + LLVM using the C++ API; +* the `mir` (4,300 LOC) folder implements the actual lowering from MIR to LLVM + IR; +* the `base.rs` (1,300 LOC) file contains some helper functions but also the + high-level code that launches the code generation and distributes the work. +* the `builder.rs` (1,200 LOC) file contains all the functions generating + individual LLVM IR instructions inside a basic block; +* the `common.rs` (450 LOC) contains various helper functions and all the + functions generating LLVM static values; +* the `type_.rs` (300 LOC) defines most of the type translations to LLVM IR. + +The goal of this refactoring is to separate inside this crate code that is +specific to the LLVM from code that can be reused for other rustc backends. For +instance, the `mir` folder is almost entirely backend-specific but it relies +heavily on other parts of the crate. The separation of the code must not affect +the logic of the code nor its performance. + +For these reasons, the separation process involves two transformations that +have to be done at the same time for the resulting code to compile : + +1. replace all the LLVM-specific types by generics inside function signatures + and structure definitions; +2. encapsulate all functions calling the LLVM FFI inside a set of traits that + will define the interface between backend-agnostic code and the backend. + +While the LLVM-specific code will be left in `rustc_codegen_llvm`, all the new +traits and backend-agnostic code will be moved in `rustc_codegen_ssa` (name +suggestion by @eddyb). + +## Generic types and structures + +@irinagpopa started to parametrize the types of `rustc_codegen_llvm` by a +generic `Value` type, implemented in LLVM by a reference `&'ll Value`. This +work has been extended to all structures inside the `mir` folder and elsewhere, +as well as for LLVM's `BasicBlock` and `Type` types. + +The two most important structures for the LLVM codegen are `CodegenCx` and +`Builder`. They are parametrized by multiple lifetime parameters and the type +for `Value`. + +```rust,ignore +struct CodegenCx<'ll, 'tcx> { + /* ... */ +} + +struct Builder<'a, 'll, 'tcx> { + cx: &'a CodegenCx<'ll, 'tcx>, + /* ... */ +} +``` + +`CodegenCx` is used to compile one codegen-unit that can contain multiple +functions, whereas `Builder` is created to compile one basic block. + +The code in `rustc_codegen_llvm` has to deal with multiple explicit lifetime +parameters, that correspond to the following: +* `'tcx` is the longest lifetime, that corresponds to the original `TyCtxt` + containing the program's information; +* `'a` is a short-lived reference of a `CodegenCx` or another object inside a + struct; +* `'ll` is the lifetime of references to LLVM objects such as `Value` or + `Type`. + +Although there are already many lifetime parameters in the code, making it +generic uncovered situations where the borrow-checker was passing only due to +the special nature of the LLVM objects manipulated (they are extern pointers). +For instance, a additional lifetime parameter had to be added to +`LocalAnalyser` in `analyse.rs`, leading to the definition: + +```rust,ignore +struct LocalAnalyzer<'mir, 'a, 'tcx> { + /* ... */ +} +``` + +However, the two most important structures `CodegenCx` and `Builder` are not +defined in the backend-agnostic code. Indeed, their content is highly specific +of the backend and it makes more sense to leave their definition to the backend +implementor than to allow just a narrow spot via a generic field for the +backend's context. + +## Traits and interface + +Because they have to be defined by the backend, `CodegenCx` and `Builder` will +be the structures implementing all the traits defining the backend's interface. +These traits are defined in the folder `rustc_codegen_ssa/traits` and all the +backend-agnostic code is parametrized by them. For instance, let us explain how +a function in `base.rs` is parametrized: + +```rust,ignore +pub fn codegen_instance<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + cx: &'a Bx::CodegenCx, + instance: Instance<'tcx> +) { + /* ... */ +} +``` + +In this signature, we have the two lifetime parameters explained earlier and +the master type `Bx` which satisfies the trait `BuilderMethods` corresponding +to the interface satisfied by the `Builder` struct. The `BuilderMethods` +defines an associated type `Bx::CodegenCx` that itself satisfies the +`CodegenMethods` traits implemented by the struct `CodegenCx`. + +On the trait side, here is an example with part of the definition of +`BuilderMethods` in `traits/builder.rs`: + +```rust,ignore +pub trait BuilderMethods<'a, 'tcx>: + HasCodegen<'tcx> + + DebugInfoBuilderMethods<'tcx> + + ArgTypeMethods<'tcx> + + AbiBuilderMethods<'tcx> + + IntrinsicCallMethods<'tcx> + + AsmBuilderMethods<'tcx> +{ + fn new_block<'b>( + cx: &'a Self::CodegenCx, + llfn: Self::Function, + name: &'b str + ) -> Self; + /* ... */ + fn cond_br( + &mut self, + cond: Self::Value, + then_llbb: Self::BasicBlock, + else_llbb: Self::BasicBlock, + ); + /* ... */ +} +``` + +Finally, a master structure implementing the `ExtraBackendMethods` trait is +used for high-level codegen-driving functions like `codegen_crate` in +`base.rs`. For LLVM, it is the empty `LlvmCodegenBackend`. +`ExtraBackendMethods` should be implemented by the same structure that +implements the `CodegenBackend` defined in +`rustc_codegen_utils/codegen_backend.rs`. + +During the traitification process, certain functions have been converted from +methods of a local structure to methods of `CodegenCx` or `Builder` and a +corresponding `self` parameter has been added. Indeed, LLVM stores information +internally that it can access when called through its API. This information +does not show up in a Rust data structure carried around when these methods are +called. However, when implementing a Rust backend for `rustc`, these methods +will need information from `CodegenCx`, hence the additional parameter (unused +in the LLVM implementation of the trait). + +## State of the code after the refactoring + +The traits offer an API which is very similar to the API of LLVM. This is not +the best solution since LLVM has a very special way of doing things: when +addding another backend, the traits definition might be changed in order to +offer more flexibility. + +However, the current separation between backend-agnostic and LLVM-specific code +has allows the reuse of a significant part of the old `rustc_codegen_llvm`. +Here is the new LOC breakdown between backend-agnostic (BA) and LLVM for the +most important elements: + +* `back` folder: 3,800 (BA) vs 4,100 (LLVM); +* `mir` folder: 4,400 (BA) vs 0 (LLVM); +* `base.rs`: 1,100 (BA) vs 250 (LLVM); +* `builder.rs`: 1,400 (BA) vs 0 (LLVM); +* `common.rs`: 350 (BA) vs 350 (LLVM); + +The `debuginfo` folder has been left almost untouched by the splitting and is +specific to LLVM. Only its high-level features have been traitified. + +The new `traits` folder has 1500 LOC only for trait definitions. Overall, the +27,000 LOC-sized old `rustc_codegen_llvm` code has been split into the new +18,500 LOC-sized new `rustc_codegen_llvm` and the 12,000 LOC-sized +`rustc_codegen_ssa`. We can say that this refactoring allowed the reuse of +approximately 10,000 LOC that would otherwise have had to be duplicated between +the multiple backends of `rustc`. + +The refactored version of `rustc`'s backend introduced no regression over the +test suite nor in performance benchmark, which is in coherence with the nature +of the refactoring that used only compile-time parametricity (no trait +objects). diff --git a/src/doc/rustc-guide/src/codegen/debugging.md b/src/doc/rustc-guide/src/codegen/debugging.md index 51d5a3b2c3..4eab306068 100644 --- a/src/doc/rustc-guide/src/codegen/debugging.md +++ b/src/doc/rustc-guide/src/codegen/debugging.md @@ -40,7 +40,7 @@ hard to replicate manually and means that LLVM is called multiple times in parallel. If you can get away with it (i.e. if it doesn't make your bug disappear), passing `-C codegen-units=1` to rustc will make debugging easier. -To rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. If +For rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. If you are building via cargo, use the `RUSTFLAGS` environment variable (e.g. `RUSTFLAGS='--emit=llvm-ir'`). This causes rustc to spit out LLVM IR into the target directory. @@ -94,6 +94,36 @@ $ ./build/$TRIPLE/llvm/bin/llvm-extract \ > extracted.ll ``` +### Getting help and asking questions + +If you have some questions, head over to the [rust-lang Zulip] and +specifically the `#t-compiler/wg-llvm` stream. + +[rust-lang Zulip]: https://rust-lang.zulipchat.com/ + +### Compiler options to know and love + +The `-Chelp` and `-Zhelp` compiler switches will list out a variety +of interesting options you may find useful. Here are a few of the most +common that pertain to LLVM development (some of them are employed in the +tutorial above): + +- The `--emit llvm-ir` option emits a `.ll` file with LLVM IR in textual format + - The `--emit llvm-bc` option emits in bytecode format (`.bc`) +- Passing `-Cllvm-args=` allows passing pretty much all the + options that tools like llc and opt would accept; + e.g. `-Cllvm-args=-print-before-all` to print IR before every LLVM + pass. +- The `-Cno-prepopulate-passes` will avoid pre-populate the LLVM pass + manager with a list of passes. This will allow you to view the LLVM + IR that rustc generates, not the LLVM IR after optimizations. +- The `-Cpasses=val` option allows you to supply a (space seprated) list of extra LLVM passes to run +- The `-Csave-temps` option saves all temporary output files during compilation +- The `-Zprint-llvm-passes` option will print out LLVM optimization passes being run +- The `-Ztime-llvm-passes` option measures the time of each LLVM pass +- The `-Zverify-llvm-ir` option will verify the LLVM IR for correctness +- The `-Zno-parallel-llvm` will disable parallel compilation of distinct compilation units + ### Filing LLVM bug reports When filing an LLVM bug report, you will probably want some sort of minimal @@ -119,4 +149,18 @@ create a minimal working example with Godbolt. Go to optimizations transform it. 5. Once you have a godbolt link demonstrating the issue, it is pretty easy to - fill in an LLVM bug. + fill in an LLVM bug. Just visit [bugs.llvm.org](https://bugs.llvm.org/). + +### Porting bug fixes from LLVM + +Once you've identified the bug as an LLVM bug, you will sometimes +find that it has already been reported and fixed in LLVM, but we haven't +gotten the fix yet (or perhaps you are familiar enough with LLVM to fix it yourself). + +In that case, we can sometimes opt to port the fix for the bug +directly to our own LLVM fork, so that rustc can use it more easily. +Our fork of LLVM is maintained in [rust-lang/llvm-project]. Once +you've landed the fix there, you'll also need to land a PR modifying +our submodule commits -- ask around on Zulip for help. + +[rust-lang/llvm-project]: https://github.com/rust-lang/llvm-project/ diff --git a/src/doc/rustc-guide/src/codegen/updating-llvm.md b/src/doc/rustc-guide/src/codegen/updating-llvm.md index 50dc949623..015514bab5 100644 --- a/src/doc/rustc-guide/src/codegen/updating-llvm.md +++ b/src/doc/rustc-guide/src/codegen/updating-llvm.md @@ -17,23 +17,26 @@ policy!), but for now these are rough guidelines! ## Why update LLVM? -There are two primary reasons nowadays that we want to update LLVM in one way or +There are a few reasons nowadays that we want to update LLVM in one way or another: -* First, a bug could have been fixed! Often we find bugs in the compiler and fix +* A bug could have been fixed! Often we find bugs in the compiler and fix them upstream in LLVM. We'll want to pull fixes back to the compiler itself as they're merged upstream. -* Second, a new feature may be available in LLVM that we want to use in rustc, +* A new feature may be available in LLVM that we want to use in rustc, but we don't want to wait for a full LLVM release to test it out. +* LLVM itself may have a new release and we'd like to update to this LLVM + release. + Each of these reasons has a different strategy for updating LLVM, and we'll go -over both in detail here. +over them in detail here. ## Bugfix Updates -For updates of LLVM that typically just update a bug, we cherry-pick the bugfix -to the branch we're already using. The steps for this are: +For updates of LLVM that are to fix a small bug, we cherry-pick the bugfix to +the branch we're already using. The steps for this are: 1. Make sure the bugfix is in upstream LLVM. 2. Identify the branch that rustc is currently using. The `src/llvm-project` @@ -43,10 +46,13 @@ to the branch we're already using. The steps for this are: 4. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`) 5. Cherry-pick the upstream commit onto the branch 6. Push this branch to your fork -7. Send a Pull Request to rust-lang/llvm-project to the same branch as before +7. Send a Pull Request to rust-lang/llvm-project to the same branch as before. + Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR + description. 8. Wait for the PR to be merged 9. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with - your bugfix + your bugfix. This can be done locally with `git submodule update --remote + src/llvm-project` typically. 10. Wait for PR to be merged The tl;dr; is that we can cherry-pick bugfixes at any time and pull them back @@ -70,7 +76,8 @@ through each in detail. 1. Create a new branch in the rust-lang/llvm-project repository. This branch should be named `rustc/a.b-yyyy-mm-dd` where `a.b` is the current version number of LLVM in-tree at the time of the branch and the remaining part is - today's date. + today's date. Move this branch to the commit in LLVM that you'd like, which + for this is probably the current LLVM HEAD. 2. Apply Rust-specific patches to the llvm-project repository. All features and bugfixes are upstream, but there's often some weird build-related patches @@ -78,20 +85,12 @@ through each in detail. patches are around the latest patches in the rust-lang/llvm-project branch that rustc is currently using. -3. Update the `compiler-rt` submodule in the - `rust-lang-nursery/compiler-builtins` repository. Push this update to the - same branch name of the `llvm-project` submodule to the - of the `rust-lang/compiler-rt` repository. Then push this update to a branch - of `compiler-builtins` with the same-named branch. Note that this step is - frequently optional since we may not need to update `compiler-rt`. - -4. Prepare a commit to rust-lang/rust - - * Update `src/llvm-project` - * Update `compiler-builtins` crate in `Cargo.lock` (if necessary) - -5. Build your commit. Make sure you've committed the previous changes to ensure - submodule updates aren't reverted. Some commands you should execute are: +3. Build the new LLVM in the `rust` repository. To do this you'll want to update + the `src/llvm-project` repository to your branch and the revision you've + created. It's also typically a good idea to update `.gitmodules` with the new + branch name of the LLVM submodule. Make sure you've committed changes to + `src/llvm-project` to ensure submodule updates aren't reverted. Some commands + you should execute are: * `./x.py build src/llvm` - test that LLVM still builds * `./x.py build src/tools/lld` - same for LLD @@ -101,7 +100,7 @@ through each in detail. LLVM bindings. Note that you should use `#ifdef` and such to ensure that the bindings still compile on older LLVM versions. -6. Test for regressions across other platforms. LLVM often has at least one bug +4. Test for regressions across other platforms. LLVM often has at least one bug for non-tier-1 architectures, so it's good to do some more testing before sending this to bors! If you're low on resources you can send the PR as-is now to bors, though, and it'll get tested anyway. @@ -120,11 +119,20 @@ through each in detail. * `./src/ci/docker/run.sh dist-various-2` * `./src/ci/docker/run.sh armhf-gnu` -7. Send a PR! Hopefully it's smooth sailing from here :). +5. Prepare a PR to `rust-lang/rust`. Work with maintainers of + `rust-lang/llvm-project` to get your commit in a branch of that repository, + and then you can send a PR to `rust-lang/rust`. You'll change at least + `src/llvm-project` and will likely also change `src/rustllvm/*` as well. For prior art, previous LLVM updates look like [#55835](https://github.com/rust-lang/rust/pull/55835) [#47828](https://github.com/rust-lang/rust/pull/47828) +[#62474](https://github.com/rust-lang/rust/pull/62474) +[#62592](https://github.com/rust-lang/rust/pull/62592). Note that sometimes it's +easiest to land `src/rustllvm/*` compatibility as a PR before actually updating +`src/llvm-project`. This way while you're working through LLVM issues others +interested in trying out the new LLVM can benefit from work you've done to +update the C++ bindings. ### Caveats and gotchas @@ -134,8 +142,36 @@ keep in mind while going through them: * LLVM bugs are hard to find, don't hesitate to ask for help! Bisection is definitely your friend here (yes LLVM takes forever to build, yet bisection is still your friend) -* Updating LLDB has some Rust-specific patches currently that aren't upstream. - If you have difficulty @tromey can likely help out. * If you've got general questions, @alexcrichton can help you out. * Creating branches is a privileged operation on GitHub, so you'll need someone with write access to create the branches for you most likely. + +## New LLVM Release Updates + +Updating to a new release of LLVM is very similar to the "feature updates" +section above. The release process for LLVM is often months-long though and we +like to ensure compatibility ASAP. The main tweaks to the "feature updates" +section above is generally around branch naming. The sequence of events +typically looks like: + +1. LLVM announces that its latest release version has branched. This will show + up as a branch in https://github.com/llvm/llvm-project typically named + `release/$N.x` where `$N` is the version of LLVM that's being released. + +2. We then follow the "feature updates" section above to create a new branch of + LLVM in our rust-lang/llvm-project repository. This follows the same naming + convention of branches as usual, except that `a.b` is the new version. This + update is eventually landed in the rust-lang/rust repository. + +3. Over the next few months, LLVM will continually push commits to its + `release/a.b` branch. Often those are bug fixes we'd like to have as well. + The merge process for that is to use `git merge` itself to merge LLVM's + `release/a.b` branch with the branch created in step 2. This is typically + done multiple times when necessary while LLVM's release branch is baking. + +4. LLVM then announces the release of version `a.b`. + +5. After LLVM's official release, we follow the "feature update" section again + to create a new branch in the rust-lang/llvm-project repository, this time + with a new date. The commit history should look much cleaner as just a few + Rust-specific commits stacked on top of stock LLVM's release branch. diff --git a/src/doc/rustc-guide/src/compiler-debugging.md b/src/doc/rustc-guide/src/compiler-debugging.md index 8f3a331aa6..736de97712 100644 --- a/src/doc/rustc-guide/src/compiler-debugging.md +++ b/src/doc/rustc-guide/src/compiler-debugging.md @@ -22,9 +22,9 @@ could be useful for debugging. When you have an ICE (panic in the compiler), you can set `RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in -normal Rust programs. IIRC backtraces **don't work** on Mac and on MinGW, +normal Rust programs. IIRC backtraces **don't work** on MinGW, sorry. If you have trouble or the backtraces are full of `unknown`, -you might want to find some way to use Linux or MSVC on Windows. +you might want to find some way to use Linux, Mac, or MSVC on Windows. In the default configuration, you don't have line numbers enabled, so the backtrace looks like this: diff --git a/src/doc/rustc-guide/src/compiler-documenting.md b/src/doc/rustc-guide/src/compiler-documenting.md deleted file mode 100644 index 97636fad5b..0000000000 --- a/src/doc/rustc-guide/src/compiler-documenting.md +++ /dev/null @@ -1,62 +0,0 @@ -# Documenting rustc - -You might want to build documentation of the various components -available like the standard library. There’s two ways to go about this. - You can run rustdoc directly on the file to make sure the HTML is - correct, which is fast. Alternatively, you can build the documentation - as part of the build process through x.py. Both are viable methods - since documentation is more about the content. - -## Document everything - - ```bash - ./x.py doc - ``` - -## If you want to avoid the whole Stage 2 build - -```bash -./x.py doc --stage 1 -``` - -First the compiler and rustdoc get built to make sure everything is okay -and then it documents the files. - -## Document specific components - -```bash - ./x.py doc src/doc/book - ./x.py doc src/doc/nomicon - ./x.py doc src/doc/book src/libstd -``` - -Much like individual tests or building certain components you can build only - the documentation you want. - -## Document internal rustc items - -Compiler documentation is not built by default. There's a flag in -config.toml for achieving the same. -But, when enabled, compiler documentation does include internal items. - -Next open up config.toml and make sure these two lines are set to true: - -```bash -docs = true -compiler-docs = true -``` - -When you want to build the compiler docs as well run this command: - -```bash -./x.py doc -``` - -This will see that the docs and compiler-docs options are set to true -and build the normally hidden compiler docs! - -### Compiler Documentation - -The documentation for the rust components are found at [rustc doc]. - -[rustc doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ \ No newline at end of file diff --git a/src/doc/rustc-guide/src/conventions.md b/src/doc/rustc-guide/src/conventions.md index 3660f33790..76933d5741 100644 --- a/src/doc/rustc-guide/src/conventions.md +++ b/src/doc/rustc-guide/src/conventions.md @@ -114,14 +114,12 @@ you introduce some code following one strategy, then change it dramatically (versus adding to it) in a later commit, that 'back-and-forth' can be confusing. -**If you run rustfmt and the file was not already formatted, isolate -that into its own commit.** This is really the same as the previous -rule, but it's worth highlighting. It's ok to rustfmt files, but since -we do not currently run rustfmt all the time, that can introduce a lot -of noise into your commit. Please isolate that into its own -commit. This also makes rebases a lot less painful, since rustfmt -tends to cause a lot of merge conflicts, and having those isolated -into their own commit makes them easier to resolve. +**Only run rustfmt on new content.** One day, we might enforce formatting +for the rust-lang/rust repo. Meanwhile, we prefer that rustfmt not be run +on existing code as that will generate large diffs and will make git blame +harder to sift through. However, running `rustfmt` on new content, e.g. a +new file or a largely new part of a file is ok. Small formatting adjustments +nearby code you are already changing for other purposes are also ok. **No merges.** We do not allow merge commits into our history, other than those by bors. If you get a merge conflict, rebase instead via a diff --git a/src/doc/rustc-guide/src/diagnostics.md b/src/doc/rustc-guide/src/diagnostics.md index f3d5187647..c6c8f4fbaa 100644 --- a/src/doc/rustc-guide/src/diagnostics.md +++ b/src/doc/rustc-guide/src/diagnostics.md @@ -31,8 +31,8 @@ usually have names like `span_err` or `struct_span_err` or `span_warn`, etc... There are lots of them; they emit different types of "errors", such as warnings, errors, fatal errors, suggestions, etc. -[parsesses]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/struct.ParseSess.html -[session]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html +[parsesses]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/sess/struct.ParseSess.html +[session]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html In general, there are two class of such methods: ones that emit an error directly and ones that allow finer control over what to emit. For example, @@ -45,8 +45,8 @@ before emitting it by calling the [`emit`][emit] method. (Failing to either emit or [cancel][cancel] a `DiagnosticBuilder` will result in an ICE.) See the [docs][diagbuild] for more info on what you can do. -[spanerr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html#method.span_err -[strspanerr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html#method.struct_span_err +[spanerr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html#method.span_err +[strspanerr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html#method.struct_span_err [diagbuild]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/diagnostic_builder/struct.DiagnosticBuilder.html [emit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/diagnostic_builder/struct.DiagnosticBuilder.html#method.emit [cancel]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diagnostic.html#method.cancel @@ -60,7 +60,7 @@ let mut err = sess.struct_span_err(sp, "oh no! this is an error!"); if let Ok(snippet) = sess.source_map().span_to_snippet(sp) { // Use the snippet to generate a suggested fix - err.span_suggestion(suggestion_sp, "try using a qux here", format!("qux {}", snip)); + err.span_suggestion(suggestion_sp, "try using a qux here", format!("qux {}", snippet)); } else { // If we weren't able to generate a snippet, then emit a "help" message // instead of a concrete "suggestion". In practice this is unlikely to be @@ -100,7 +100,7 @@ if let Ok(snippet) = sess.source_map().span_to_snippet(sp) { err.span_suggestion( suggestion_sp, "try using a qux here", - format!("qux {}", snip), + format!("qux {}", snippet), Applicability::MachineApplicable, ); } else { @@ -171,11 +171,17 @@ crate. [builtin]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/index.html -Each lint is defined as a `struct` that implements the `LintPass` `trait`. The -trait implementation allows you to check certain syntactic constructs the -linter walks the source code. You can then choose to emit lints in a very -similar way to compile errors. Finally, you register the lint to actually get -it to be run by the compiler by using the `declare_lint!` macro. +Every lint is implemented via a `struct` that implements the `LintPass` `trait` +(you also implement one of the more specific lint pass traits, either +`EarlyLintPass` or `LateLintPass`). The trait implementation allows you to +check certain syntactic constructs as the linter walks the source code. You can +then choose to emit lints in a very similar way to compile errors. + +You also declare the metadata of a particular lint via the `declare_lint!` +macro. This includes the name, the default level, a short description, and some +more details. + +Note that the lint and the lint pass must be registered with the compiler. For example, the following lint checks for uses of `while true { ... }` and suggests using `loop { ... }` instead. @@ -196,11 +202,15 @@ declare_lint! { #[derive(Copy, Clone)] pub struct WhileTrue; -impl LintPass for WhileTrue { - fn get_lints(&self) -> LintArray { - lint_array!(WHILE_TRUE) - } -} +// This declares a lint pass, providing a list of associated lints. The +// compiler currently doesn't use the associated lints directly (e.g., to not +// run the pass or otherwise check that the pass emits the appropriate set of +// lints). However, it's good to be accurate here as it's possible that we're +// going to register the lints via the get_lints method on our lint pass (that +// this macro generates). +impl_lint_pass!( + WhileTrue => [WHILE_TRUE], +); // LateLintPass has lots of methods. We only override the definition of // `check_expr` for this lint because that's all we need, but you could @@ -242,9 +252,33 @@ declare_lint! { This makes the `ANONYMOUS_PARAMETERS` lint allow-by-default in the 2015 edition but warn-by-default in the 2018 edition. -Lints that represent an incompatibility (i.e. error) in the upcoming edition -should also be registered as `FutureIncompatibilityLint`s in -[`register_builtins`][rbuiltins] function in [`rustc_lint::lib`][builtin]. +A future-incompatible lint should be declared with the `@future_incompatible` +additional "field": + +```rust,ignore +declare_lint! { + pub ANONYMOUS_PARAMETERS, + Allow, + "detects anonymous parameters", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #41686 ", + edition: Some(Edition::Edition2018), + }; +} +``` + +If you need a combination of options that's not supported by the +`declare_lint!` macro, you can always define your own static with a type of +`&Lint` but this is currently linted against in the compiler tree. + +#### Guidelines for creating a future incompatibility lint + +- Create a lint defaulting to warn as normal, with ideally the same error + message you would normally give. +- Add a suitable reference, typically an RFC or tracking issue. Go ahead + and include the full URL, sort items in ascending order of issue numbers. +- Later, change lint to error. +- Eventually, remove lint. ### Lint Groups @@ -257,11 +291,11 @@ Lints can be turned on in groups. These groups are declared in the For example, ```rust,ignore - add_lint_group!(sess, - "nonstandard_style", - NON_CAMEL_CASE_TYPES, - NON_SNAKE_CASE, - NON_UPPER_CASE_GLOBALS); +add_lint_group!(sess, + "nonstandard_style", + NON_CAMEL_CASE_TYPES, + NON_SNAKE_CASE, + NON_UPPER_CASE_GLOBALS); ``` This defines the `nonstandard_style` group which turns on the listed lints. A @@ -280,8 +314,8 @@ processed. [`Session`][sessbl] and [`ParseSess`][parsebl] both have `buffer_lint` methods that allow you to buffer a lint for later. The linting system automatically takes care of handling buffered lints later. -[sessbl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html#method.buffer_lint -[parsebl]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/struct.ParseSess.html#method.buffer_lint +[sessbl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html#method.buffer_lint +[parsebl]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/sess/struct.ParseSess.html#method.buffer_lint Thus, to define a lint that runs early in the compilation, one defines a lint like normal but invokes the lint with `buffer_lint`. @@ -297,15 +331,6 @@ To solve this, `libsyntax` defines its own buffered lint type, which `ParseSess::buffer_lint` uses. After macro expansion, these buffered lints are then dumped into the `Session::buffered_lints` used by the rest of the compiler. -Usage for buffered lints in `libsyntax` is pretty much the same as the rest of -the compiler with one exception because we cannot import the `LintId`s for -lints we want to emit. Instead, the [`BufferedEarlyLintId`] type is used. If you -are defining a new lint, you will want to add an entry to this enum. Then, add -an appropriate mapping to the body of [`Lint::from_parser_lint_id`][fplid]. - -[`BufferedEarlyLintId`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/early_buffered_lints/enum.BufferedEarlyLintId.html -[fplid]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/struct.Lint.html#method.from_parser_lint_id - ## JSON diagnostic output The compiler accepts an `--error-format json` flag to output @@ -342,3 +367,150 @@ The JSON emitter defines [its own `Diagnostic` struct](https://github.com/rust-lang/rust/blob/b2c6b8c29f13f8d1f242da89e587960b95337819/src/libsyntax/json.rs#L85-L99) (and sub-structs) for the JSON serialization. Don't confuse this with [`errors::Diagnostic`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diagnostic.html)! + +## `#[rustc_on_unimplemented(...)]` + +The `#[rustc_on_unimplemented]` attribute allows trait definitions to add specialized +notes to error messages when an implementation was expected but not found. +You can refer to the trait's generic arguments by name and to the resolved type using `Self`. + +For example: + +```rust,ignore +#![feature(rustc_attrs)] + +#[rustc_on_unimplemented="an iterator over elements of type `{A}` \ + cannot be built from a collection of type `{Self}`"] +trait MyIterator { + fn next(&mut self) -> A; +} + +fn iterate_chars>(i: I) { + // ... +} + +fn main() { + iterate_chars(&[1, 2, 3][..]); +} +``` + +When the user compiles this, they will see the following; + +```txt +error[E0277]: the trait bound `&[{integer}]: MyIterator` is not satisfied + --> :14:5 + | +14 | iterate_chars(&[1, 2, 3][..]); + | ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]` + | + = help: the trait `MyIterator` is not implemented for `&[{integer}]` + = note: required by `iterate_chars` +``` + +`rustc_on_unimplemented` also supports advanced filtering for better targeting +of messages, as well as modifying specific parts of the error message. You +target the text of: + + - the main error message (`message`) + - the label (`label`) + - an extra note (`note`) + +For example, the following attribute + +```rust,ignore +#[rustc_on_unimplemented( + message="message", + label="label", + note="note" +)] +trait MyIterator { + fn next(&mut self) -> A; +} +``` + +Would generate the following output: + +```text +error[E0277]: message + --> :14:5 + | +14 | iterate_chars(&[1, 2, 3][..]); + | ^^^^^^^^^^^^^ label + | + = note: note + = help: the trait `MyIterator` is not implemented for `&[{integer}]` + = note: required by `iterate_chars` +``` + +To allow more targeted error messages, it is possible to filter the +application of these fields based on a variety of attributes when using +`on`: + + - `crate_local`: whether the code causing the trait bound to not be + fulfilled is part of the user's crate. This is used to avoid suggesting + code changes that would require modifying a dependency. + - Any of the generic arguments that can be substituted in the text can be + referred by name as well for filtering, like `Rhs="i32"`, except for + `Self`. + - `_Self`: to filter only on a particular calculated trait resolution, like + `Self="std::iter::Iterator"`. This is needed because `Self` is a + keyword which cannot appear in attributes. + - `direct`: user-specified rather than derived obligation. + - `from_method`: usable both as boolean (whether the flag is present, like + `crate_local`) or matching against a particular method. Currently used + for `try`. + - `from_desugaring`: usable both as boolean (whether the flag is present) + or matching against a particular desugaring. The desugaring is identified + with its variant name in the `DesugaringKind` enum. + +For example, the `Iterator` trait can be annotated in the following way: + +```rust,ignore +#[rustc_on_unimplemented( + on( + _Self="&str", + note="call `.chars()` or `.as_bytes()` on `{Self}" + ), + message="`{Self}` is not an iterator", + label="`{Self}` is not an iterator", + note="maybe try calling `.iter()` or a similar method" +)] +pub trait Iterator {} +``` + +Which would produce the following outputs: + +```text +error[E0277]: `Foo` is not an iterator + --> src/main.rs:4:16 + | +4 | for foo in Foo {} + | ^^^ `Foo` is not an iterator + | + = note: maybe try calling `.iter()` or a similar method + = help: the trait `std::iter::Iterator` is not implemented for `Foo` + = note: required by `std::iter::IntoIterator::into_iter` + +error[E0277]: `&str` is not an iterator + --> src/main.rs:5:16 + | +5 | for foo in "" {} + | ^^ `&str` is not an iterator + | + = note: call `.chars()` or `.bytes() on `&str` + = help: the trait `std::iter::Iterator` is not implemented for `&str` + = note: required by `std::iter::IntoIterator::into_iter` +``` + +If you need to filter on multiple attributes, you can use `all`, `any` or +`not` in the following way: + +```rust,ignore +#[rustc_on_unimplemented( + on( + all(_Self="&str", T="std::string::String"), + note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`" + ) +)] +pub trait From: Sized { /* ... */ } +``` diff --git a/src/doc/rustc-guide/src/diagnostics/json-format.md b/src/doc/rustc-guide/src/diagnostics/json-format.md deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/doc/rustc-guide/src/diagnostics/lintstore.md b/src/doc/rustc-guide/src/diagnostics/lintstore.md new file mode 100644 index 0000000000..32e6ef8b87 --- /dev/null +++ b/src/doc/rustc-guide/src/diagnostics/lintstore.md @@ -0,0 +1,105 @@ +# Lints + +This page documents some of the machinery around lint registration and how we +run lints in the compiler. + +The `LintStore` is the central piece of infrastructure, around which everything +rotates. It's not available during the early parts of compilation (i.e., before +TyCtxt) in most code, as we need to fill it in with all of the lints, which can only happen after +plugin registration. + +## Lints vs. lint passes + +There are two parts to the linting mechanism within the compiler: lints and lint passes. +Unfortunately, a lot of the documentation we have refers to both of these as just "lints." + +First, we have the lint declarations themselves: this is where the name and default lint level and +other metadata come from. These are normally defined by way of the [`declare_lint!`] macro, which +boils down to a static with type `&rustc::lint::Lint`. We lint against direct declarations without +the use of the macro today (though this may change in the future, as the macro is somewhat unwieldy +to add new fields to, like all macros by example). + +Lint declarations don't carry any "state" - they are merely global identifers and descriptions of +lints. We assert at runtime that they are not registered twice (by lint name). + +Lint passes are the meat of any lint. Notably, there is not a one-to-one relationship between +lints and lint passes; a lint might not have any lint pass that emits it, it could have many, or +just one -- the compiler doesn't track whether a pass is in any way associated with a particular +lint, and frequently lints are emitted as part of other work (e.g., type checking, etc.). + +## Registration + +### High-level overview + +The lint store is created and all lints are registered during plugin registration, in +[`rustc_interface::register_plugins`]. There are three 'sources' of lint: the internal lints, plugin +lints, and `rustc_interface::Config` [`register_lints`]. All are registered here, in +`register_plugins`. + +Once the registration is complete, we "freeze" the lint store by placing it in an `Lrc`. Later in +the driver, it's passed into the `GlobalCtxt` constructor where it lives in an immutable form from +then on. + +Lints are registered via the [`LintStore::register_lint`] function. This should +happen just once for any lint, or an ICE will occur. + +Lint passes are registered separately into one of the categories (pre-expansion, +early, late, late module). Passes are registered as a closure -- i.e., `impl +Fn() -> Box`, where `dyn X` is either an early or late lint pass trait +object. When we run the lint passes, we run the closure and then invoke the lint +pass methods, which take `&mut self` -- lint passes can keep track of state +internally. + +#### Internal lints + +Note, these include both rustc-internal lints, and the traditional lints, like, for example the dead +code lint. + +These are primarily described in two places: `rustc::lint::builtin` and `rustc_lint::builtin`. The +first provides the definitions for the lints themselves, and the latter provides the lint pass +definitions (and implementations). + +The internal lint registration happens in the [`rustc_lint::register_builtins`] function, along with +the [`rustc_lint::register_internals`] function. More generally, the LintStore "constructor" +function which is *the* way to get a `LintStore` in the compiler (you should not construct it +directly) is [`rustc_lint::new_lint_store`]; it calls the registration functions. + +#### Plugin lints + +This is one of the primary use cases remaining for plugins/drivers. Plugins are given access to the +mutable `LintStore` during registration to call any functions they need on the `LintStore`, just +like rustc code. Plugins are intended to declare lints with the `plugin` field set to true (e.g., by +way of the [`declare_tool_lint!`] macro), but this is purely for diagnostics and help text; +otherwise plugin lints are mostly just as first class as rustc builtin lints. + +#### Driver lints + +These are the lints provided by drivers via the `rustc_interface::Config` [`register_lints`] field, +which is a callback. Drivers should, if finding it already set, call the function currently set +within the callback they add. The best way for drivers to get access to this is by overriding the +`Callbacks::config` function which gives them direct access to the `Config` structure. + +## Compiler lint passes are combined into one pass + +Within the compiler, for performance reasons, we usually do not register dozens +of lint passes. Instead, we have a single lint pass of each variety +(e.g. `BuiltinCombinedModuleLateLintPass`) which will internally call all of the +individual lint passes; this is because then we get the benefits of static over +dynamic dispatch for each of the (often empty) trait methods. + +Ideally, we'd not have to do this, since it certainly adds to the complexity of +understanding the code. However, with the current type-erased lint store +approach, it is beneficial to do so for performance reasons. + +New lints being added likely want to join one of the existing declarations like +`late_lint_mod_passes` in `librustc_lint/lib.rs`, which would then +auto-propagate into the other. + +[`LintStore::register_lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/struct.LintStore.html#method.register_lints +[`rustc_interface::register_plugins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.register_plugins.html +[`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html +[`rustc_lint::register_internals`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_internals.html +[`rustc_lint::new_lint_store`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.new_lint_store.html +[`declare_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_lint.html +[`declare_tool_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_tool_lint.html +[`register_lints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html#structfield.register_lints diff --git a/src/doc/rustc-guide/src/generic_arguments.md b/src/doc/rustc-guide/src/generic_arguments.md new file mode 100644 index 0000000000..c9911acf56 --- /dev/null +++ b/src/doc/rustc-guide/src/generic_arguments.md @@ -0,0 +1,50 @@ +# Generic arguments +A `ty::subst::GenericArg<'tcx>` represents some entity in the type system: a type +(`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). +`GenericArg` is used to perform substitutions of generic parameters for concrete +arguments, such as when calling a function with generic parameters explicitly +with type arguments. Substitutions are represented using the +[`Subst` type](#subst) as described below. + +## `Subst` +`ty::subst::Subst<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, +acting as an ordered list of substitutions from generic parameters to +concrete arguments (such as types, lifetimes and consts). + +For example, given a `HashMap` with two type parameters, `K` and `V`, an +instantiation of the parameters, for example `HashMap`, would be +represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. + +`Subst` provides various convenience methods to instantiate substitutions +given item definitions, which should generally be used rather than explicitly +constructing such substitution slices. + +## `GenericArg` +The actual `GenericArg` struct is optimised for space, storing the type, lifetime or +const as an interned pointer containing a tag identifying its kind (in the +lowest 2 bits). Unless you are working with the `Subst` implementation +specifically, you should generally not have to deal with `GenericArg` and instead +make use of the safe [`GenericArgKind`](#genericargkind) abstraction. + +## `GenericArgKind` +As `GenericArg` itself is not type-safe, the `GenericArgKind` enum provides a more +convenient and safe interface for dealing with generic arguments. An +`GenericArgKind` can be converted to a raw `GenericArg` using `GenericArg::from()` +(or simply `.into()` when the context is clear). As mentioned earlier, substitution +lists store raw `GenericArg`s, so before dealing with them, it is preferable to +convert them to `GenericArgKind`s first. This is done by calling the `.unpack()` +method. + +```rust,ignore +// An example of unpacking and packing a generic argument. +fn deal_with_generic_arg<'tcx>(generic_arg: GenericArg<'tcx>) -> GenericArg<'tcx> { + // Unpack a raw `GenericArg` to deal with it safely. + let new_generic_arg: GenericArgKind<'tcx> = match generic_arg.unpack() { + GenericArgKind::Type(ty) => { /* ... */ } + GenericArgKind::Lifetime(lt) => { /* ... */ } + GenericArgKind::Const(ct) => { /* ... */ } + }; + // Pack the `GenericArgKind` to store it in a substitution list. + new_generic_arg.into() +} +``` diff --git a/src/doc/rustc-guide/src/high-level-overview.md b/src/doc/rustc-guide/src/high-level-overview.md index 93b5592c3a..6255590344 100644 --- a/src/doc/rustc-guide/src/high-level-overview.md +++ b/src/doc/rustc-guide/src/high-level-overview.md @@ -8,7 +8,7 @@ standard library and the compiler. This document, of course, focuses on the latter. Rustc consists of a number of crates, including `syntax`, -`rustc`, `rustc_back`, `rustc_codegen`, `rustc_driver`, and +`rustc`, `rustc_target`, `rustc_codegen`, `rustc_driver`, and many more. The source for each crate can be found in a directory like `src/libXXX`, where `XXX` is the crate name. @@ -66,10 +66,6 @@ of the compiler and not intended to be stable (though they do wind up getting used by some crates in the wild; a practice we hope to gradually phase out). -Each crate has a `README.md` file that describes, at a high-level, -what it contains, and tries to give some kind of explanation (some -better than others). - ## The main stages of compilation The Rust compiler is in a bit of transition right now. It used to be a @@ -139,4 +135,4 @@ take: [query model]: query.html [high-level intermediate representation]: hir.html -[lowering]: lowering.html \ No newline at end of file +[lowering]: lowering.html diff --git a/src/doc/rustc-guide/src/hir.md b/src/doc/rustc-guide/src/hir.md index b100422701..0a48d11238 100644 --- a/src/doc/rustc-guide/src/hir.md +++ b/src/doc/rustc-guide/src/hir.md @@ -15,7 +15,7 @@ You can view the HIR representation of your code by passing the `-Zunpretty=hir-tree` flag to rustc: ```bash -> cargo rustc -- -Zunpretty=hir-tree +cargo rustc -- -Zunpretty=hir-tree ``` ### Out-of-band storage and the `Crate` type diff --git a/src/doc/rustc-guide/src/how-to-build-and-run.md b/src/doc/rustc-guide/src/how-to-build-and-run.md deleted file mode 100644 index aac0f211c5..0000000000 --- a/src/doc/rustc-guide/src/how-to-build-and-run.md +++ /dev/null @@ -1,533 +0,0 @@ -# How to Build and Run the Compiler - -The compiler is built using a tool called `x.py`. You will need to -have Python installed to run it. But before we get to that, if you're going to -be hacking on `rustc`, you'll want to tweak the configuration of the compiler. -The default configuration is oriented towards running the compiler as a user, -not a developer. - -### Create a config.toml - -To start, copy [`config.toml.example`] to `config.toml`: - -[`config.toml.example`]: https://github.com/rust-lang/rust/blob/master/config.toml.example - -```bash -> cd $RUST_CHECKOUT -> cp config.toml.example config.toml -``` - -Then you will want to open up the file and change the following -settings (and possibly others, such as `llvm.ccache`): - -```toml -[llvm] -# Enables LLVM assertions, which will check that the LLVM bitcode generated -# by the compiler is internally consistent. These are particularly helpful -# if you edit `codegen`. -assertions = true - -[rust] -# This will make your build more parallel; it costs a bit of runtime -# performance perhaps (less inlining) but it's worth it. -codegen-units = 0 - -# This enables full debuginfo and debug assertions. The line debuginfo is also -# enabled by `debuginfo-level = 1`. Full debuginfo is also enabled by -# `debuginfo-level = 2`. Debug assertions can also be enabled with -# `debug-assertions = true`. Note that `debug = true` will make your build -# slower, so you may want to try individually enabling debuginfo and assertions -# or enable only line debuginfo which is basically free. -debug = true -``` - -If you have already built `rustc`, then you may have to execute `rm -rf build` for subsequent -configuration changes to take effect. Note that `./x.py clean` will not cause a -rebuild of LLVM, so if your configuration change affects LLVM, you will need to -manually `rm -rf build/` before rebuilding. - -### What is `x.py`? - -`x.py` is the script used to orchestrate the tooling in the `rustc` repository. -It is the script that can build docs, run tests, and compile `rustc`. -It is the now preferred way to build `rustc` and it replaces the old makefiles -from before. Below are the different ways to utilize `x.py` in order to -effectively deal with the repo for various common tasks. - -### Running `x.py` and building a stage1 compiler - -One thing to keep in mind is that `rustc` is a _bootstrapping_ -compiler. That is, since `rustc` is written in Rust, we need to use an -older version of the compiler to compile the newer version. In -particular, the newer version of the compiler and some of the artifacts needed -to build it, such as `libstd` and other tooling, may use some unstable features -internally, requiring a specific version which understands these unstable -features. - -The result is that compiling `rustc` is done in stages: - -- **Stage 0:** the stage0 compiler is usually (you can configure `x.py` to use - something else) the current _beta_ `rustc` compiler and its associated dynamic - libraries (which `x.py` will download for you). This stage0 compiler is then - used only to compile `rustbuild`, `std`, and `rustc`. When compiling - `rustc`, this stage0 compiler uses the freshly compiled `std`. - There are two concepts at play here: a compiler (with its set of dependencies) - and its 'target' or 'object' libraries (`std` and `rustc`). - Both are staged, but in a staggered manner. -- **Stage 1:** the code in your clone (for new version) is then - compiled with the stage0 compiler to produce the stage1 compiler. - However, it was built with an older compiler (stage0), so to - optimize the stage1 compiler we go to next the stage. - - In theory, the stage1 compiler is functionally identical to the - stage2 compiler, but in practice there are subtle differences. In - particular, the stage1 compiler itself was built by stage0 and - hence not by the source in your working directory: this means that - the symbol names used in the compiler source may not match the - symbol names that would have been made by the stage1 compiler. - This can be important when using dynamic linking (e.g., with - derives. Sometimes this means that some tests don't work when run - with stage1. -- **Stage 2:** we rebuild our stage1 compiler with itself to produce - the stage2 compiler (i.e. it builds itself) to have all the _latest - optimizations_. (By default, we copy the stage1 libraries for use by - the stage2 compiler, since they ought to be identical.) -- _(Optional)_ **Stage 3**: to sanity check our new compiler, we - can build the libraries with the stage2 compiler. The result ought - to be identical to before, unless something has broken. - -#### A note on stage meanings - -When running `x.py` you will see output such as: - -```txt -Building stage0 std artifacts -Copying stage0 std from stage0 -Building stage0 compiler artifacts -Copying stage0 rustc from stage0 -Building LLVM for x86_64-apple-darwin -Building stage0 codegen artifacts -Assembling stage1 compiler -Building stage1 std artifacts -Copying stage1 std from stage1 -Building stage1 compiler artifacts -Copying stage1 rustc from stage1 -Building stage1 codegen artifacts -Assembling stage2 compiler -Uplifting stage1 std -Copying stage2 std from stage1 -Generating unstable book md files -Building stage0 tool unstable-book-gen -Building stage0 tool rustbook -Documenting standalone -Building rustdoc for stage2 -Documenting book redirect pages -Documenting stage2 std -Building rustdoc for stage1 -Documenting stage2 whitelisted compiler -Documenting stage2 compiler -Documenting stage2 rustdoc -Documenting error index -Uplifting stage1 rustc -Copying stage2 rustc from stage1 -Building stage2 tool error_index_generator -``` - -A deeper look into `x.py`'s phases can be seen here: - -A diagram of the rustc compilation phases - -Keep in mind this diagram is a simplification, i.e. `rustdoc` can be built at -different stages, the process is a bit different when passing flags such as -`--keep-stage`, or if there are non-host targets. - -The following tables indicate the outputs of various stage actions: - -| Stage 0 Action | Output | -|-----------------------------------------------------------|----------------------------------------------| -| `beta` extracted | `build/HOST/stage0` | -| `stage0` builds `bootstrap` | `build/bootstrap` | -| `stage0` builds `libstd` | `build/HOST/stage0-std/TARGET` | -| copy `stage0-std` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | -| `stage0` builds `rustc` with `stage0-sysroot` | `build/HOST/stage0-rustc/HOST` | -| copy `stage0-rustc (except executable)` | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | -| build `llvm` | `build/HOST/llvm` | -| `stage0` builds `codegen` with `stage0-sysroot` | `build/HOST/stage0-codegen/HOST` | -| `stage0` builds `rustdoc` with `stage0-sysroot` | `build/HOST/stage0-tools/HOST` | - -`--stage=0` stops here. - -| Stage 1 Action | Output | -|-----------------------------------------------------|---------------------------------------| -| copy (uplift) `stage0-rustc` executable to `stage1` | `build/HOST/stage1/bin` | -| copy (uplift) `stage0-codegen` to `stage1` | `build/HOST/stage1/lib` | -| copy (uplift) `stage0-sysroot` to `stage1` | `build/HOST/stage1/lib` | -| `stage1` builds `libstd` | `build/HOST/stage1-std/TARGET` | -| copy `stage1-std` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` | -| `stage1` builds `rustc` | `build/HOST/stage1-rustc/HOST` | -| copy `stage1-rustc` (except executable) | `build/HOST/stage1/lib/rustlib/HOST` | -| `stage1` builds `codegen` | `build/HOST/stage1-codegen/HOST` | - -`--stage=1` stops here. - -| Stage 2 Action | Output | -|-------------------------------------------|-----------------------------------------------------------------| -| copy (uplift) `stage1-rustc` executable | `build/HOST/stage2/bin` | -| copy (uplift) `stage1-sysroot` | `build/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST` | -| `stage2` builds `libstd` (except HOST?) | `build/HOST/stage2-std/TARGET` | -| copy `stage2-std` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` | -| `stage2` builds `rustdoc` | `build/HOST/stage2-tools/HOST` | -| copy `rustdoc` | `build/HOST/stage2/bin` | - -`--stage=2` stops here. - -Note that the convention `x.py` uses is that: -- A "stage N artifact" is an artifact that is _produced_ by the stage N compiler. -- The "stage (N+1) compiler" is assembled from "stage N artifacts". -- A `--stage N` flag means build _with_ stage N. - -In short, _stage 0 uses the stage0 compiler to create stage0 artifacts which -will later be uplifted to stage1_. - -Every time any of the main artifacts (`std` and `rustc`) are compiled, two -steps are performed. -When `std` is compiled by a stage N compiler, that `std` will be linked to -programs built by the stage N compiler (including `rustc` built later -on). It will also be used by the stage (N+1) compiler to link against itself. -This is somewhat intuitive if one thinks of the stage (N+1) compiler as "just" -another program we are building with the stage N compiler. In some ways, `rustc` -(the binary, not the `rustbuild` step) could be thought of as one of the few -`no_core` binaries out there. - -So "stage0 std artifacts" are in fact the output of the downloaded stage0 -compiler, and are going to be used for anything built by the stage0 compiler: -e.g. `rustc` artifacts. When it announces that it is "building stage1 -std artifacts" it has moved on to the next bootstrapping phase. This pattern -continues in latter stages. - -Also note that building host `std` and target `std` are different based on the -stage (e.g. see in the table how stage2 only builds non-host `std` targets. -This is because during stage2, the host `std` is uplifted from the "stage 1" -`std` -- specifically, when "Building stage 1 artifacts" is announced, it is -later copied into stage2 as well (both the compiler's `libdir` and the -`sysroot`). - -This `std` is pretty much necessary for any useful work with the compiler. -Specifically, it's used as the `std` for programs compiled by the newly compiled -compiler (so when you compile `fn main() { }` it is linked to the last `std` -compiled with `x.py build --stage 1 src/libstd`). - -The `rustc` generated by the stage0 compiler is linked to the freshly-built -`libstd`, which means that for the most part only `std` needs to be cfg-gated, -so that `rustc` can use featured added to std immediately after their addition, -without need for them to get into the downloaded beta. The `libstd` built by the -`stage1/bin/rustc` compiler, also known as "stage1 std artifacts", is not -necessarily ABI-compatible with that compiler. -That is, the `rustc` binary most likely could not use this `std` itself. -It is however ABI-compatible with any programs that the `stage1/bin/rustc` -binary builds (including itself), so in that sense they're paired. - -This is also where `--keep-stage 1 src/libstd` comes into play. Since most -changes to the compiler don't actually change the ABI, once you've produced a -`libstd` in stage 1, you can probably just reuse it with a different compiler. -If the ABI hasn't changed, you're good to go, no need to spend the time -recompiling that `std`. -`--keep-stage` simply assumes the previous compile is fine and copies those -artifacts into the appropriate place, skipping the cargo invocation. - -The reason we first build `std`, then `rustc`, is largely just -because we want to minimize `cfg(stage0)` in the code for `rustc`. -Currently `rustc` is always linked against a "new" `std` so it doesn't -ever need to be concerned with differences in std; it can assume that the std is -as fresh as possible. - -The reason we need to build it twice is because of ABI compatibility. -The beta compiler has it's own ABI, and then the `stage1/bin/rustc` compiler -will produce programs/libraries with the new ABI. -We used to build three times, but because we assume that the ABI is constant -within a codebase, we presume that the libraries produced by the "stage2" -compiler (produced by the `stage1/bin/rustc` compiler) is ABI-compatible with -the `stage1/bin/rustc` compiler's produced libraries. -What this means is that we can skip that final compilation -- and simply use the -same libraries as the `stage2/bin/rustc` compiler uses itself for programs it -links against. - -This `stage2/bin/rustc` compiler is shipped to end-users, along with the -`stage 1 {std,rustc}` artifacts. - -If you want to learn more about `x.py`, read its README.md -[here](https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md). - -#### Build Flags - -There are other flags you can pass to the build command of `x.py` that can be -beneficial to cutting down compile times or fitting other things you might -need to change. They are: - -```txt -Options: - -v, --verbose use verbose output (-vv for very verbose) - -i, --incremental use incremental compilation - --config FILE TOML configuration file for build - --build BUILD build target of the stage0 compiler - --host HOST host targets to build - --target TARGET target targets to build - --on-fail CMD command to run on failure - --stage N stage to build - --keep-stage N stage to keep without recompiling - --src DIR path to the root of the rust checkout - -j, --jobs JOBS number of jobs to run in parallel - -h, --help print this help message -``` - -For hacking, often building the stage 1 compiler is enough, but for -final testing and release, the stage 2 compiler is used. - -`./x.py check` is really fast to build the rust compiler. -It is, in particular, very useful when you're doing some kind of -"type-based refactoring", like renaming a method, or changing the -signature of some function. - - - -Once you've created a config.toml, you are now ready to run -`x.py`. There are a lot of options here, but let's start with what is -probably the best "go to" command for building a local rust: - -```bash -> ./x.py build -i --stage 1 src/libstd -``` - -This may *look* like it only builds libstd, but that is not the case. -What this command does is the following: - -- Build `libstd` using the stage0 compiler (using incremental) -- Build `librustc` using the stage0 compiler (using incremental) - - This produces the stage1 compiler -- Build libstd using the stage1 compiler (cannot use incremental) - -This final product (stage1 compiler + libs built using that compiler) -is what you need to build other rust programs (unless you use `#![no_std]` or -`#![no_core]`). - -The command includes the `-i` switch which enables incremental compilation. -This will be used to speed up the first two steps of the process: -in particular, if you make a small change, we ought to be able to use your old -results to make producing the stage1 **compiler** faster. - -Unfortunately, incremental cannot be used to speed up making the -stage1 libraries. This is because incremental only works when you run -the *same compiler* twice in a row. In this case, we are building a -*new stage1 compiler* every time. Therefore, the old incremental -results may not apply. **As a result, you will probably find that -building the stage1 `libstd` is a bottleneck for you** -- but fear not, -there is a (hacky) workaround. See [the section on "recommended -workflows"](#workflow) below. - -Note that this whole command just gives you a subset of the full `rustc` -build. The **full** `rustc` build (what you get if you just say `./x.py -build`) has quite a few more steps: - -- Build `librustc` and `rustc` with the stage1 compiler. - - The resulting compiler here is called the "stage2" compiler. -- Build libstd with stage2 compiler. -- Build librustdoc and a bunch of other things with the stage2 compiler. - - - -### Build specific components - - Build only the libcore library - -```bash -> ./x.py build src/libcore -``` - - Build the libcore and libproc_macro library only - -```bash -> ./x.py build src/libcore src/libproc_macro -``` - - Build only libcore up to Stage 1 - -```bash -> ./x.py build src/libcore --stage 1 -``` - -Sometimes you might just want to test if the part you’re working on can -compile. Using these commands you can test that it compiles before doing -a bigger build to make sure it works with the compiler. As shown before -you can also pass flags at the end such as --stage. - -### Creating a rustup toolchain - -Once you have successfully built `rustc`, you will have created a bunch -of files in your `build` directory. In order to actually run the -resulting `rustc`, we recommend creating rustup toolchains. The first -one will run the stage1 compiler (which we built above). The second -will execute the stage2 compiler (which we did not build, but which -you will likely need to build at some point; for example, if you want -to run the entire test suite). - -```bash -> rustup toolchain link stage1 build//stage1 -> rustup toolchain link stage2 build//stage2 -``` - -The `` would typically be one of the following: - -- Linux: `x86_64-unknown-linux-gnu` -- Mac: `x86_64-apple-darwin` -- Windows: `x86_64-pc-windows-msvc` - -Now you can run the `rustc` you built with. If you run with `-vV`, you -should see a version number ending in `-dev`, indicating a build from -your local environment: - -```bash -> rustc +stage1 -vV -rustc 1.25.0-dev -binary: rustc -commit-hash: unknown -commit-date: unknown -host: x86_64-unknown-linux-gnu -release: 1.25.0-dev -LLVM version: 4.0 -``` - - - -### Suggested workflows for faster builds of the compiler - -There are two workflows that are useful for faster builds of the compiler. - -**Check, check, and check again.** The first workflow, which is useful -when doing simple refactorings, is to run `./x.py check` -continuously. Here you are just checking that the compiler can -**build**, but often that is all you need (e.g., when renaming a -method). You can then run `./x.py build` when you actually need to -run tests. - -In fact, it is sometimes useful to put off tests even when you are not -100% sure the code will work. You can then keep building up -refactoring commits and only run the tests at some later time. You can -then use `git bisect` to track down **precisely** which commit caused -the problem. A nice side-effect of this style is that you are left -with a fairly fine-grained set of commits at the end, all of which -build and pass tests. This often helps reviewing. - -**Incremental builds with `--keep-stage`.** Sometimes just checking -whether the compiler builds is not enough. A common example is that -you need to add a `debug!` statement to inspect the value of some -state or better understand the problem. In that case, you really need -a full build. By leveraging incremental, though, you can often get -these builds to complete very fast (e.g., around 30 seconds). The only -catch is this requires a bit of fudging and may produce compilers that -don't work (but that is easily detected and fixed). - -The sequence of commands you want is as follows: - -- Initial build: `./x.py build -i --stage 1 src/libstd` - - As [documented above](#command), this will build a functional - stage1 compiler as part of running all stage0 commands (which include - building a `libstd` compatible with the stage1 compiler) as well as the - first few steps of the "stage 1 actions" up to "stage1 (sysroot stage1) - builds libstd". -- Subsequent builds: `./x.py build -i --stage 1 src/libstd --keep-stage 1` - - Note that we added the `--keep-stage 1` flag here - -As mentioned, the effect of `--keep-stage 1` is that we just *assume* that the -old standard library can be re-used. If you are editing the compiler, this -is almost always true: you haven't changed the standard library, after -all. But sometimes, it's not true: for example, if you are editing -the "metadata" part of the compiler, which controls how the compiler -encodes types and other states into the `rlib` files, or if you are -editing things that wind up in the metadata (such as the definition of -the MIR). - -**The TL;DR is that you might get weird behavior from a compile when -using `--keep-stage 1`** -- for example, strange -[ICEs](appendix/glossary.html) or other panics. In that case, you -should simply remove the `--keep-stage 1` from the command and -rebuild. That ought to fix the problem. - -You can also use `--keep-stage 1` when running tests. Something like this: - -- Initial test run: `./x.py test -i --stage 1 src/test/ui` -- Subsequent test run: `./x.py test -i --stage 1 src/test/ui --keep-stage 1` - -### Building with system LLVM - -By default, LLVM is built from source, and that can take significant amount of time. -An alternative is to use LLVM already installed on your computer. - -This is specified in the `target` section of `config.toml`: - -```toml -[target.x86_64-unknown-linux-gnu] -llvm-config = "/path/to/llvm/llvm-7.0.1/bin/llvm-config" -``` - -### Other `x.py` commands - -Here are a few other useful `x.py` commands. We'll cover some of them in detail -in other sections: - -- Building things: - - `./x.py clean` – clean up the build directory (`rm -rf build` works too, - but then you have to rebuild LLVM) - - `./x.py build --stage 1` – builds everything using the stage 1 compiler, - not just up to libstd - - `./x.py build` – builds the stage2 compiler -- Running tests (see the [section on running tests](./tests/running.html) for - more details): - - `./x.py test --stage 1 src/libstd` – runs the `#[test]` tests from libstd - - `./x.py test --stage 1 src/test/ui` – runs the `ui` test suite - - `./x.py test --stage 1 src/test/ui/const-generics` - runs all the tests in - the `const-generics/` subdirectory of the `ui` test suite - - `./x.py test --stage 1 src/test/ui/const-generics/const-types.rs` - runs - the single test `const-types.rs` from the `ui` test suite - -### ctags - -One of the challenges with rustc is that the RLS can't handle it, since it's a -bootstrapping compiler. This makes code navigation difficult. One solution is to -use `ctags`. - -`ctags` has a long history and several variants. Exuberant Ctags seems to be -quite commonly distributed but it does not have out-of-box Rust support. Some -distributions seem to use [Universal Ctags][utags], which is a maintained fork -and does have built-in Rust support. - -The following script can be used to set up Exuberant Ctags: -[https://github.com/nikomatsakis/rust-etags][etags]. - -`ctags` integrates into emacs and vim quite easily. The following can then be -used to build and generate tags: - -```console -$ rust-ctags src/lib* && ./x.py build -``` - -This allows you to do "jump-to-def" with whatever functions were around when -you last built, which is ridiculously useful. - -[etags]: https://github.com/nikomatsakis/rust-etags -[utags]: https://github.com/universal-ctags/ctags - -### Cleaning out build directories - -Sometimes you need to start fresh, but this is normally not the case. -If you need to run this then rustbuild is most likely not acting right and -you should file a bug as to what is going wrong. If you do need to clean -everything up then you only need to run one command! - - ```bash - > ./x.py clean - ``` - -### Compiler Documentation - -The documentation for the rust components are found at [rustc doc]. - -[rustc doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ diff --git a/src/doc/rustc-guide/src/ice-breaker/about.md b/src/doc/rustc-guide/src/ice-breaker/about.md new file mode 100644 index 0000000000..7869bdbce9 --- /dev/null +++ b/src/doc/rustc-guide/src/ice-breaker/about.md @@ -0,0 +1,68 @@ +# ICE-breakers + +The **ICE-breaker groups** are an easy way to help out with rustc in a +"piece-meal" fashion, without committing to a larger project. +ICE-breaker groups are **[easy to join](#join)** (just submit a PR!) +and joining does not entail any particular commitment. + +Once you [join an ICE ICE-breaker group](#join), you will be added to +a list that receives pings on github whenever a new issue is found +that fits the ICE-breaker group's criteria. If you are interested, you +can then [claim the issue] and start working on it. + +Of course, you don't have to wait for new issues to be tagged! If you +prefer, you can use the Github label for an ICE-breaker group to +search for existing issues that haven't been claimed yet. + +[claim the issue]: https://github.com/rust-lang/triagebot/wiki/Assignment + +## What issues are a good fit for ICE-breaker groups? + +"ICE-breaker issues" are intended to be **isolated** bugs of **middle +priority**: + +- By **isolated**, we mean that we do not expect large-scale refactoring + to be required to fix the bug. +- By **middle priority**, we mean that we'd like to see the bug fixed, + but it's not such a burning problem that we are dropping everything + else to fix it. The danger with such bugs, of course, is that they + can accumulate over time, and the role of the ICE-breaker groups is + to try and stop that from happening! + + + +## Joining an ICE-breaker group + +To join an ICE-breaker group, you just have to open a PR adding your +Github username to the appropriate file in the Rust team repository. +See the "example PRs" below to get a precise idea and to identify the +file to edit. + +Also, if you are not already a member of a Rust team then -- in addition +to adding your name to the file -- you have to checkout the repository and +run the following command: + +```bash +cargo run add-person $your_user_name +``` + +Example PRs: + +* [Example of adding yourself to the LLVM ICE-breakers.](https://github.com/rust-lang/team/pull/140) + +## Tagging an issue for an ICE-breaker group + +To tag an issue as appropriate for an ICE-breaker group, you give +[rustbot] a [`ping`] command with the name of the ICE-breakers +team. For example: + +```text +@rustbot ping icebreakers-llvm +``` + +**Note though that this should only be done by compiler team members +or contributors, and is typically done as part of compiler team +triage.** + +[rustbot]: https://github.com/rust-lang/triagebot/ +[`ping`]: https://github.com/rust-lang/triagebot/wiki/Pinging diff --git a/src/doc/rustc-guide/src/ice-breaker/llvm.md b/src/doc/rustc-guide/src/ice-breaker/llvm.md new file mode 100644 index 0000000000..e0c90fdafc --- /dev/null +++ b/src/doc/rustc-guide/src/ice-breaker/llvm.md @@ -0,0 +1,31 @@ +# LLVM ICE-breakers + +**Github Label:** [ICEBreaker-LLVM] + +[ICEBreaker-LLVM]: https://github.com/rust-lang/rust/labels/ICEBreaker-LLVM + +The "LLVM ICE-breakers" are focused on bugs that center around LLVM. +These bugs often arise because of LLVM optimizations gone awry, or as +the result of an LLVM upgrade. The goal here is: + +- to determine whether the bug is a result of us generating invalid LLVM IR, + or LLVM misoptimizing; +- if the former, to fix our IR; +- if the latter, to try and file a bug on LLVM (or identify an existing bug). + +## Helpful tips and options + +The ["Debugging LLVM"][d] section of the +rustc-guide gives a step-by-step process for how to help debug bugs +caused by LLVM. In particular, it discusses how to emit LLVM IR, run +the LLVM IR optimization pipeliness, and so forth. You may also find +it useful to look at the various codegen options listed under `-Chelp` +and the internal options under `-Zhelp` -- there are a number that +pertain to LLVM (just search for LLVM). + +[d]: ../codegen/debugging.md + +## If you do narrow to an LLVM bug + +The ["Debugging LLVM"][d] section also describes what to do once +you've identified the bug. diff --git a/src/doc/rustc-guide/src/implementing_new_features.md b/src/doc/rustc-guide/src/implementing_new_features.md index 6d1327fabb..4b2529fff1 100644 --- a/src/doc/rustc-guide/src/implementing_new_features.md +++ b/src/doc/rustc-guide/src/implementing_new_features.md @@ -35,7 +35,7 @@ of concept so that people can see what you are talking about. That starts a "proposed final comment period" (pFCP), which requires all members of the team to sign off the FCP. After they all do so, -there's a week long "final comment period" where everybody can comment, +there's a 10 day long "final comment period" where everybody can comment, and if no new concerns are raised, the PR/issue gets FCP approval. ## The logistics of writing features @@ -99,15 +99,15 @@ for YOUR FEATURE". For tracking issues for features (as opposed to future-compat warnings), I don't think the description has to contain anything specific. Generally we put the list of items required -for stabilization using a github list, e.g. +for stabilization in a checklist, e.g., ```txt - **Steps:** +**Steps:** - - [ ] Implement the RFC (cc @rust-lang/compiler -- can anyone write - up mentoring instructions?) - - [ ] Adjust documentation ([see instructions on forge][doc-guide]) - - Note: no stabilization step here. +- [ ] Implement the RFC. (CC @rust-lang/compiler -- can anyone write + up mentoring instructions?) +- [ ] Adjust the documentation. ([See instructions on rustc-guide.](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#documentation-prs)) +- [ ] Stabilize the feature. ([See instructions on rustc-guide.](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#stabilization-pr)) ``` @@ -119,29 +119,32 @@ a new unstable feature: 1. Open a [tracking issue] - if you have an RFC, you can use the tracking issue for the RFC. + The tracking issue should be labeled with at least `C-tracking-issue`. + For a language feature, a label `F-feature_name` should be added as well. + 2. Pick a name for the feature gate (for RFCs, use the name in the RFC). -3. Add a feature gate declaration to `libsyntax/feature_gate.rs` +3. Add a feature gate declaration to `libsyntax/feature_gate/active.rs` in the active `declare_features` block: -```rust,ignore - // description of feature - (active, $feature_name, "$current_nightly_version", Some($tracking_issue_number), $edition) -``` + ```rust,ignore + // description of feature + (active, $feature_name, "$current_nightly_version", Some($tracking_issue_number), $edition) + ``` -where `$edition` has the type `Option`, and is typically -just `None`. + where `$edition` has the type `Option`, and is typically + just `None`. -For example: + For example: -```rust,ignore - // allow '|' at beginning of match arms (RFC 1925) -( active, match_beginning_vert, "1.21.0", Some(44101), None), -``` + ```rust,ignore + /// Allows defining identifiers beyond ASCII. + (active, non_ascii_idents, "1.0.0", Some(55467), None), + ``` -The current version is not actually important – the important -version is when you are stabilizing a feature. + When added, the current version should be the one for the current nightly. + Once the feature is moved to `accepted.rs`, the version is changed to that nightly version. 4. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the @@ -153,10 +156,14 @@ version is when you are stabilizing a feature. the pre-feature behavior or raise an error, depending on what makes sense. + For features introducing new syntax, pre-expansion gating should be used instead. + To do so, extend the [`GatedSpans`] struct, add spans to it during parsing, + and then finally feature-gate all the spans in [`feature_gate::check::check_crate`]. + 5. Add a test to ensure the feature cannot be used without a feature gate, by creating `feature-gate-$feature_name.rs` and `feature-gate-$feature_name.stderr` files under the - `src/test/ui/feature-gates` directory. + directory where the other tests for your feature reside. 6. Add a section to the unstable book, in `src/doc/unstable-book/src/language-features/$feature_name.md`. @@ -167,7 +174,9 @@ version is when you are stabilizing a feature. 8. Get your PR reviewed and land it. You have now successfully implemented a feature in Rust! +[`GatedSpans`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/sess/struct.GatedSpans.html +[`feature_gate::check::check_crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/feature_gate/check/fn.check_crate.html [value the stability of Rust]: https://github.com/rust-lang/rfcs/blob/master/text/1122-language-semver.md [stability in code]: #stability-in-code -[here]: https://rust-lang.github.io/rustc-guide/stabilization_guide.html +[here]: ./stabilization_guide.md [tracking issue]: #tracking-issue diff --git a/src/doc/rustc-guide/src/important-links.md b/src/doc/rustc-guide/src/important-links.md deleted file mode 100644 index 367532519c..0000000000 --- a/src/doc/rustc-guide/src/important-links.md +++ /dev/null @@ -1,16 +0,0 @@ -# Ignore me - -This file is a collection of links that are not link-checked by anyone else, -but we want them to work. For example, the stabilization guide link is often -posted to tracking issues on GitHub, which might break later if the guide is -changed. - -[Skip this file. Or read it; I'm a book, not a cop.](https://imgur.com/gallery/mSHi8) - -[link](https://forge.rust-lang.org/stabilization-guide.html) -[link](https://forge.rust-lang.org/stabilization-guide.html#updating-documentation) -[link](https://forge.rust-lang.org/stabilization-guide.html#documentation-prs) - -[link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html) -[link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#updating-documentation) -[link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#documentation-prs) diff --git a/src/doc/rustc-guide/src/kinds.md b/src/doc/rustc-guide/src/kinds.md deleted file mode 100644 index 194d2ee2ff..0000000000 --- a/src/doc/rustc-guide/src/kinds.md +++ /dev/null @@ -1,49 +0,0 @@ -# Kinds -A `ty::subst::Kind<'tcx>` represents some entity in the type system: a type -(`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). -`Kind` is used to perform substitutions of generic parameters for concrete -arguments, such as when calling a function with generic parameters explicitly -with type arguments. Substitutions are represented using the -[`Subst` type](#subst) as described below. - -## `Subst` -`ty::subst::Subst<'tcx>` is intuitively simply a slice of `Kind<'tcx>`s, -acting as an ordered list of substitutions from generic parameters to -concrete arguments (such as types, lifetimes and consts). - -For example, given a `HashMap` with two type parameters, `K` and `V`, an -instantiation of the parameters, for example `HashMap`, would be -represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. - -`Subst` provides various convenience methods to instantiate substitutions -given item definitions, which should generally be used rather than explicitly -constructing such substitution slices. - -## `Kind` -The actual `Kind` struct is optimised for space, storing the type, lifetime or -const as an interned pointer containing a tag identifying its kind (in the -lowest 2 bits). Unless you are working with the `Subst` implementation -specifically, you should generally not have to deal with `Kind` and instead -make use of the safe [`UnpackedKind`](#unpackedkind) abstraction. - -## `UnpackedKind` -As `Kind` itself is not type-safe, the `UnpackedKind` enum provides a more -convenient and safe interface for dealing with kinds. An `UnpackedKind` can -be converted to a raw `Kind` using `Kind::from()` (or simply `.into()` when -the context is clear). As mentioned earlier, substitution lists store raw -`Kind`s, so before dealing with them, it is preferable to convert them to -`UnpackedKind`s first. This is done by calling the `.unpack()` method. - -```rust,ignore -// An example of unpacking and packing a kind. -fn deal_with_kind<'tcx>(kind: Kind<'tcx>) -> Kind<'tcx> { - // Unpack a raw `Kind` to deal with it safely. - let new_kind: UnpackedKind<'tcx> = match kind.unpack() { - UnpackedKind::Type(ty) => { /* ... */ } - UnpackedKind::Lifetime(lt) => { /* ... */ } - UnpackedKind::Const(ct) => { /* ... */ } - }; - // Pack the `UnpackedKind` to store it in a substitution list. - new_kind.into() -} -``` diff --git a/src/doc/rustc-guide/src/macro-expansion.md b/src/doc/rustc-guide/src/macro-expansion.md index bb429282f4..a3a3ae7623 100644 --- a/src/doc/rustc-guide/src/macro-expansion.md +++ b/src/doc/rustc-guide/src/macro-expansion.md @@ -1,5 +1,8 @@ # Macro expansion +> `libsyntax`, `librustc_expand`, and `libsyntax_ext` are all undergoing +> refactoring, so some of the links in this chapter may be broken. + Macro expansion happens during parsing. `rustc` has two parsers, in fact: the normal Rust parser, and the macro parser. During the parsing phase, the normal Rust parser will set aside the contents of macros and their invocations. Later, @@ -7,7 +10,7 @@ before name resolution, macros are expanded using these portions of the code. The macro parser, in turn, may call the normal Rust parser when it needs to bind a metavariable (e.g. `$my_expr`) while parsing the contents of a macro invocation. The code for macro expansion is in -[`src/libsyntax/ext/tt/`][code_dir]. This chapter aims to explain how macro +[`src/libsyntax_expand/mbe/`][code_dir]. This chapter aims to explain how macro expansion works. ### Example @@ -61,7 +64,7 @@ invocations. Interestingly, both are done by the macro parser. Basically, the macro parser is like an NFA-based regex parser. It uses an algorithm similar in spirit to the [Earley parsing algorithm](https://en.wikipedia.org/wiki/Earley_parser). The macro parser is -defined in [`src/libsyntax/ext/tt/macro_parser.rs`][code_mp]. +defined in [`src/libsyntax_expand/mbe/macro_parser.rs`][code_mp]. The interface of the macro parser is as follows (this is slightly simplified): @@ -110,7 +113,7 @@ normal Rust parser. As mentioned above, both definitions and invocations of macros are parsed using the macro parser. This is extremely non-intuitive and self-referential. The code to parse macro _definitions_ is in -[`src/libsyntax/ext/tt/macro_rules.rs`][code_mr]. It defines the pattern for +[`src/libsyntax_expand/mbe/macro_rules.rs`][code_mr]. It defines the pattern for matching for a macro definition as `$( $lhs:tt => $rhs:tt );+`. In other words, a `macro_rules` definition should have in its body at least one occurrence of a token tree followed by `=>` followed by another token tree. When the compiler @@ -139,7 +142,7 @@ the parse is ambiguous, while if there are no matches at all, there is a syntax error. For more information about the macro parser's implementation, see the comments -in [`src/libsyntax/ext/tt/macro_parser.rs`][code_mp]. +in [`src/libsyntax_expand/mbe/macro_parser.rs`][code_mp]. ### Hygiene @@ -205,8 +208,711 @@ TODO TODO: maybe something about macros 2.0? -[code_dir]: https://github.com/rust-lang/rust/tree/master/src/libsyntax/ext/tt -[code_mp]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ext/tt/macro_parser/ -[code_mr]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ext/tt/macro_rules/ -[code_parse_int]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ext/tt/macro_parser/fn.parse.html +[code_dir]: https://github.com/rust-lang/rust/tree/master/src/libsyntax_expand/mbe +[code_mp]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax_expand/mbe/macro_parser +[code_mr]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax_expand/mbe/macro_rules +[code_parse_int]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax_expand/mbe/macro_parser/fn.parse.html [parsing]: ./the-parser.html + + +# Discussion about hygiene + +The rest of this chapter is a dump of a discussion between `mark-i-m` and +`petrochenkov` about Macro Expansion and Hygiene. I am pasting it here so that +it never gets lost until we can make it into a proper chapter. + +```txt +mark-i-m: @Vadim Petrochenkov Hi :wave: +I was wondering if you would have a chance sometime in the next month or so to +just have a zulip discussion where you tell us (WG-learning) everything you +know about macros/expansion/hygiene. We were thinking this could be less formal +(and less work for you) than compiler lecture series lecture... thoughts? + +mark-i-m: The goal is to fill out that long-standing gap in the rustc-guide + +Vadim Petrochenkov: Ok, I'm at UTC+03:00 and generally available in the +evenings (or weekends). + +mark-i-m: @Vadim Petrochenkov Either of those works for me (your evenings are +about lunch time for me :) ) Is there a particular date that would work best +for you? + +mark-i-m: @WG-learning Does anyone else have a preferred date? + + Vadim Petrochenkov: + + Is there a particular date that would work best for you? + +Nah, not much difference. (If something changes for a specific day, I'll +notify.) + +Santiago Pastorino: week days are better, but I'd say let's wait for @Vadim +Petrochenkov to say when they are ready for it and we can set a date + +Santiago Pastorino: also, we should record this so ... I guess it doesn't +matter that much when :) + + mark-i-m: + + also, we should record this so ... I guess it doesn't matter that much when + :) + +@Santiago Pastorino My thinking was to just use zulip, so we would have the log + +mark-i-m: @Vadim Petrochenkov @WG-learning How about 2 weeks from now: July 24 +at 5pm UTC time (if I did the math right, that should be evening for Vadim) + +Amanjeev Sethi: i can try and do this but I am starting a new job that week so +cannot promise. + + Santiago Pastorino: + + Vadim Petrochenkov @WG-learning How about 2 weeks from now: July 24 at 5pm + UTC time (if I did the math right, that should be evening for Vadim) + +works perfect for me + +Santiago Pastorino: @mark-i-m I have access to the compiler calendar so I can +add something there + +Santiago Pastorino: let me know if you want to add an event to the calendar, I +can do that + +Santiago Pastorino: how long it would be? + + mark-i-m: + + let me know if you want to add an event to the calendar, I can do that + +mark-i-m: That could be good :+1: + + mark-i-m: + + how long it would be? + +Let's start with 30 minutes, and if we need to schedule another we cna + + Vadim Petrochenkov: + + 5pm UTC + +1-2 hours later would be better, 5pm UTC is not evening enough. + +Vadim Petrochenkov: How exactly do you plan the meeting to go (aka how much do +I need to prepare)? + + Santiago Pastorino: + + 5pm UTC + + 1-2 hours later would be better, 5pm UTC is not evening enough. + +Scheduled for 7pm UTC then + + Santiago Pastorino: + + How exactly do you plan the meeting to go (aka how much do I need to + prepare)? + +/cc @mark-i-m + +mark-i-m: @Vadim Petrochenkov + + How exactly do you plan the meeting to go (aka how much do I need to + prepare)? + +My hope was that this could be less formal than for a compiler lecture series, +but it would be nice if you could have in your mind a tour of the design and +the code + +That is, imagine that a new person was joining the compiler team and needed to +get up to speed about macros/expansion/hygiene. What would you tell such a +person? + +mark-i-m: @Vadim Petrochenkov Are we still on for tomorrow at 7pm UTC? + +Vadim Petrochenkov: Yes. + +Santiago Pastorino: @Vadim Petrochenkov @mark-i-m I've added an event on rust +compiler team calendar + +mark-i-m: @WG-learning @Vadim Petrochenkov Hello! + +mark-i-m: We will be starting in ~7 minutes + +mark-i-m: :wave: + +Vadim Petrochenkov: I'm here. + +mark-i-m: Cool :) + +Santiago Pastorino: hello @Vadim Petrochenkov + +mark-i-m: Shall we start? + +mark-i-m: First off, @Vadim Petrochenkov Thanks for doing this! + +Vadim Petrochenkov: Here's some preliminary data I prepared. + +Vadim Petrochenkov: Below I'll assume #62771 and #62086 has landed. + +Vadim Petrochenkov: Where to find the code: libsyntax_pos/hygiene.rs - +structures related to hygiene and expansion that are kept in global data (can +be accessed from any Ident without any context) libsyntax_pos/lib.rs - some +secondary methods like macro backtrace using primary methods from hygiene.rs +libsyntax_ext - implementations of built-in macros (including macro attributes +and derives) and some other early code generation facilities like injection of +standard library imports or generation of test harness. libsyntax/config.rs - +implementation of cfg/cfg_attr (they treated specially from other macros), +should probably be moved into libsyntax/ext. libsyntax/tokenstream.rs + +libsyntax/parse/token.rs - structures for compiler-side tokens, token trees, +and token streams. libsyntax/ext - various expansion-related stuff +libsyntax/ext/base.rs - basic structures used by expansion +libsyntax/ext/expand.rs - some expansion structures and the bulk of expansion +infrastructure code - collecting macro invocations, calling into resolve for +them, calling their expanding functions, and integrating the results back into +AST libsyntax/ext/placeholder.rs - the part of expand.rs responsible for +"integrating the results back into AST" basicallly, "placeholder" is a +temporary AST node replaced with macro expansion result nodes +libsyntax/ext/builer.rs - helper functions for building AST for built-in macros +in libsyntax_ext (and user-defined syntactic plugins previously), can probably +be moved into libsyntax_ext these days libsyntax/ext/proc_macro.rs + +libsyntax/ext/proc_macro_server.rs - interfaces between the compiler and the +stable proc_macro library, converting tokens and token streams between the two +representations and sending them through C ABI libsyntax/ext/tt - +implementation of macro_rules, turns macro_rules DSL into something with +signature Fn(TokenStream) -> TokenStream that can eat and produce tokens, +@mark-i-m knows more about this librustc_resolve/macros.rs - resolving macro +paths, validating those resolutions, reporting various "not found"/"found, but +it's unstable"/"expected x, found y" errors librustc/hir/map/def_collector.rs + +librustc_resolve/build_reduced_graph.rs - integrate an AST fragment freshly +expanded from a macro into various parent/child structures like module +hierarchy or "definition paths" + +Primary structures: HygieneData - global piece of data containing hygiene and +expansion info that can be accessed from any Ident without any context ExpnId - +ID of a macro call or desugaring (and also expansion of that call/desugaring, +depending on context) ExpnInfo/InternalExpnData - a subset of properties from +both macro definition and macro call available through global data +SyntaxContext - ID of a chain of nested macro definitions (identified by +ExpnIds) SyntaxContextData - data associated with the given SyntaxContext, +mostly a cache for results of filtering that chain in different ways Span - a +code location + SyntaxContext Ident - interned string (Symbol) + Span, i.e. a +string with attached hygiene data TokenStream - a collection of TokenTrees +TokenTree - a token (punctuation, identifier, or literal) or a delimited group +(anything inside ()/[]/{}) SyntaxExtension - a lowered macro representation, +contains its expander function transforming a tokenstream or AST into +tokenstream or AST + some additional data like stability, or a list of unstable +features allowed inside the macro. SyntaxExtensionKind - expander functions +may have several different signatures (take one token stream, or two, or a +piece of AST, etc), this is an enum that lists them +ProcMacro/TTMacroExpander/AttrProcMacro/MultiItemModifier - traits representing +the expander signatures (TODO: change and rename the signatures into something +more consistent) trait Resolver - a trait used to break crate dependencies (so +resolver services can be used in libsyntax, despite librustc_resolve and pretty +much everything else depending on libsyntax) ExtCtxt/ExpansionData - various +intermediate data kept and used by expansion infra in the process of its work +AstFragment - a piece of AST that can be produced by a macro (may include +multiple homogeneous AST nodes, like e.g. a list of items) Annotatable - a +piece of AST that can be an attribute target, almost same thing as AstFragment +except for types and patterns that can be produced by macros but cannot be +annotated with attributes (TODO: Merge into AstFragment) trait MacResult - a +"polymorphic" AST fragment, something that can turn into a different +AstFragment depending on its context (aka AstFragmentKind - item, or +expression, or pattern etc.) Invocation/InvocationKind - a structure describing +a macro call, these structures are collected by the expansion infra +(InvocationCollector), queued, resolved, expanded when resolved, etc. + +Primary algorithms / actions: TODO + +mark-i-m: Very useful :+1: + +mark-i-m: @Vadim Petrochenkov Zulip doesn't have an indication of typing, so +I'm not sure if you are waiting for me or not + +Vadim Petrochenkov: The TODO part should be about how a crate transitions from +the state "macros exist as written in source" to "all macros are expanded", but +I didn't write it yet. + +Vadim Petrochenkov: (That should probably better happen off-line.) + +Vadim Petrochenkov: Now, if you have any questions? + +mark-i-m: Thanks :) + +mark-i-m: /me is still reading :P + +mark-i-m: Ok + +mark-i-m: So I guess my first question is about hygiene, since that remains the +most mysterious to me... My understanding is that the parser outputs AST nodes, +where each node has a Span + +mark-i-m: In the absence of macros and desugaring, what does the syntax context +of an AST node look like? + +mark-i-m: @Vadim Petrochenkov + +Vadim Petrochenkov: Not each node, but many of them. When a node is not +macro-expanded, its context is 0. + +Vadim Petrochenkov: aka SyntaxContext::empty() + +Vadim Petrochenkov: it's a chain that consists of one expansion - expansion 0 +aka ExpnId::root. + +mark-i-m: Do all expansions start at root? + +Vadim Petrochenkov: Also, SyntaxContext:empty() is its own father. + +mark-i-m: Is this actually stored somewhere or is it a logical value? + +Vadim Petrochenkov: All expansion hyerarchies (there are several of them) start +at ExpnId::root. + +Vadim Petrochenkov: Vectors in HygieneData has entries for both ctxt == 0 and +expn_id == 0. + +Vadim Petrochenkov: I don't think anyone looks into them much though. + +mark-i-m: Ok + +Vadim Petrochenkov: Speaking of multiple hierarchies... + +mark-i-m: Go ahead :) + +Vadim Petrochenkov: One is parent (expn_id1) -> parent(expn_id2) -> ... + +Vadim Petrochenkov: This is the order in which macros are expanded. + +Vadim Petrochenkov: Well. + +Vadim Petrochenkov: When we are expanding one macro another macro is revealed +in its output. + +Vadim Petrochenkov: That's the parent-child relation in this hierarchy. + +Vadim Petrochenkov: InternalExpnData::parent is the child->parent link. + +mark-i-m: So in the above chain expn_id1 is the child? + +Vadim Petrochenkov: Yes. + +Vadim Petrochenkov: The second one is parent (SyntaxContext1) -> +parent(SyntaxContext2) -> ... + +Vadim Petrochenkov: This is about nested macro definitions. When we are +expanding one macro another macro definition is revealed in its output. + +Vadim Petrochenkov: SyntaxContextData::parent is the child->parent link here. + +Vadim Petrochenkov: So, SyntaxContext is the whole chain in this hierarchy, and +outer_expns are individual elements in the chain. + +mark-i-m: So for example, suppose I have the following: + +macro_rules! foo { () => { println!(); } } + +fn main() { foo!(); } + +Then AST nodes that are finally generated would have parent(expn_id_println) -> +parent(expn_id_foo), right? + +Vadim Petrochenkov: Pretty common construction (at least it was, before +refactorings) is SyntaxContext::empty().apply_mark(expn_id), which means... + + Vadim Petrochenkov: + + Then AST nodes that are finally generated would have + parent(expn_id_println) -> parent(expn_id_foo), right? + +Yes. + + mark-i-m: + + and outer_expns are individual elements in the chain. + +Sorry, what is outer_expns? + +Vadim Petrochenkov: SyntaxContextData::outer_expn + +mark-i-m: Thanks :) Please continue + +Vadim Petrochenkov: ...which means a token produced by a built-in macro (which +is defined in the root effectively). + +mark-i-m: Where does the expn_id come from? + +Vadim Petrochenkov: Or a stable proc macro, which are always considered to be +defined in the root because they are always cross-crate, and we don't have the +cross-crate hygiene implemented, ha-ha. + + Vadim Petrochenkov: + + Where does the expn_id come from? + +Vadim Petrochenkov: ID of the built-in macro call like line!(). + +Vadim Petrochenkov: Assigned continuously from 0 to N as soon as we discover +new macro calls. + +mark-i-m: Sorry, I didn't quite understand. Do you mean that only built-in +macros receive continuous IDs? + +Vadim Petrochenkov: So, the second hierarchy has a catch - the context +transplantation hack - +https://github.com/rust-lang/rust/pull/51762#issuecomment-401400732. + + Vadim Petrochenkov: + + Do you mean that only built-in macros receive continuous IDs? + +Vadim Petrochenkov: No, all macro calls receive ID. + +Vadim Petrochenkov: Built-ins have the typical pattern +SyntaxContext::empty().apply_mark(expn_id) for syntax contexts produced by +them. + +mark-i-m: I see, but this pattern is only used for built-ins, right? + +Vadim Petrochenkov: And also all stable proc macros, see the comments above. + +mark-i-m: Got it + +Vadim Petrochenkov: The third hierarchy is call-site hierarchy. + +Vadim Petrochenkov: If foo!(bar!(ident)) expands into ident + +Vadim Petrochenkov: then hierarchy 1 is root -> foo -> bar -> ident + +Vadim Petrochenkov: but hierarchy 3 is root -> ident + +Vadim Petrochenkov: ExpnInfo::call_site is the child-parent link in this case. + +mark-i-m: When we expand, do we expand foo first or bar? Why is there a +hierarchy 1 here? Is that foo expands first and it expands to something that +contains bar!(ident)? + +Vadim Petrochenkov: Ah, yes, let's assume both foo and bar are identity macros. + +Vadim Petrochenkov: Then foo!(bar!(ident)) -> expand -> bar!(ident) -> expand +-> ident + +Vadim Petrochenkov: If bar were expanded first, that would be eager expansion - +https://github.com/rust-lang/rfcs/pull/2320. + +mark-i-m: And after we expand only foo! presumably whatever intermediate state +has heirarchy 1 of root->foo->(bar_ident), right? + +Vadim Petrochenkov: (We have it hacked into some built-in macros, but not +generally.) + + Vadim Petrochenkov: + + And after we expand only foo! presumably whatever intermediate state has + heirarchy 1 of root->foo->(bar_ident), right? + +Vadim Petrochenkov: Yes. + +mark-i-m: Got it :) + +mark-i-m: It looks like we have ~5 minutes left. This has been very helpful +already, but I also have more questions. Shall we try to schedule another +meeting in the future? + +Vadim Petrochenkov: Sure, why not. + +Vadim Petrochenkov: A thread for offline questions-answers would be good too. + + mark-i-m: + + A thread for offline questions-answers would be good too. + +I don't mind using this thread, since it already has a lot of info in it. We +also plan to summarize the info from this thread into the rustc-guide. + + Sure, why not. + +Unfortunately, I'm unavailable for a few weeks. Would August 21-ish work for +you (and @WG-learning )? + +mark-i-m: @Vadim Petrochenkov Thanks very much for your time and knowledge! + +mark-i-m: One last question: are there more hierarchies? + +Vadim Petrochenkov: Not that I know of. Three + the context transplantation +hack is already more complex than I'd like. + +mark-i-m: Yes, one wonders what it would be like if one also had to think about +eager expansion... + +Santiago Pastorino: sorry but I couldn't follow that much today, will read it +when I have some time later + +Santiago Pastorino: btw https://github.com/rust-lang/rustc-guide/issues/398 + +mark-i-m: @Vadim Petrochenkov Would 7pm UTC on August 21 work for a followup? + +Vadim Petrochenkov: Tentatively yes. + +mark-i-m: @Vadim Petrochenkov @WG-learning Does this still work for everyone? + +Vadim Petrochenkov: August 21 is still ok. + +mark-i-m: @WG-learning @Vadim Petrochenkov We will start in ~30min + +Vadim Petrochenkov: Oh. Thanks for the reminder, I forgot about this entirely. + +mark-i-m: Hello! + +Vadim Petrochenkov: (I'll be here in a couple of minutes.) + +Vadim Petrochenkov: Ok, I'm here. + +mark-i-m: Hi :) + +Vadim Petrochenkov: Hi. + +mark-i-m: so last time, we talked about the 3 context heirarchies + +Vadim Petrochenkov: Right. + +mark-i-m: Was there anything you wanted to add to that? If not, I think it +would be good to get a big-picture... Given some piece of rust code, how do we +get to the point where things are expanded and hygiene context is computed? + +mark-i-m: (I'm assuming that hygiene info is computed as we expand stuff, since +I don't think you can discover it beforehand) + +Vadim Petrochenkov: Ok, let's move from hygiene to expansion. + +Vadim Petrochenkov: Especially given that I don't remember the specific hygiene +algorithms like adjust in detail. + + Vadim Petrochenkov: + + Given some piece of rust code, how do we get to the point where things are + expanded + +So, first of all, the "some piece of rust code" is the whole crate. + +mark-i-m: Just to confirm, the algorithms are well-encapsulated, right? Like a +function or a struct as opposed to a bunch of conventions distributed across +the codebase? + +Vadim Petrochenkov: We run fully_expand_fragment in it. + + Vadim Petrochenkov: + + Just to confirm, the algorithms are well-encapsulated, right? + +Yes, the algorithmic parts are entirely inside hygiene.rs. + +Vadim Petrochenkov: Ok, some are in fn resolve_crate_root, but those are hacks. + +Vadim Petrochenkov: (Continuing about expansion.) If fully_expand_fragment is +run not on a whole crate, it means that we are performing eager expansion. + +Vadim Petrochenkov: Eager expansion is done for arguments of some built-in +macros that expect literals. + +Vadim Petrochenkov: It generally performs a subset of actions performed by the +non-eager expansion. + +Vadim Petrochenkov: So, I'll talk about non-eager expansion for now. + +mark-i-m: Eager expansion is not exposed as a language feature, right? i.e. it +is not possible for me to write an eager macro? + +Vadim Petrochenkov: +https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049 (vvv The +link is explained below vvv ) + + Vadim Petrochenkov: + + Eager expansion is not exposed as a language feature, right? i.e. it is not + possible for me to write an eager macro? + +Yes, it's entirely an ability of some built-in macros. + +Vadim Petrochenkov: Not exposed for general use. + +Vadim Petrochenkov: fully_expand_fragment works in iterations. + +Vadim Petrochenkov: Iterations looks roughly like this: +- Resolve imports in our partially built crate as much as possible. +- Collect as many macro invocations as possible from our partially built crate + (fn-like, attributes, derives) from the crate and add them to the queue. + + Vadim Petrochenkov: Take a macro from the queue, and attempt to resolve it. + + Vadim Petrochenkov: If it's resolved - run its expander function that + consumes tokens or AST and produces tokens or AST (depending on the macro + kind). + + Vadim Petrochenkov: (If it's not resolved, then put it back into the + queue.) + +Vadim Petrochenkov: ^^^ That's where we fill in the hygiene data associated +with ExpnIds. + +mark-i-m: When we put it back in the queue? + +mark-i-m: or do you mean the collect step in general? + +Vadim Petrochenkov: Once we resolved the macro call to the macro definition we +know everything about the macro and can call set_expn_data to fill in its +properties in the global data. + +Vadim Petrochenkov: I mean, immediately after successful resolution. + +Vadim Petrochenkov: That's the first part of hygiene data, the second one is +associated with SyntaxContext rather than with ExpnId, it's filled in later +during expansion. + +Vadim Petrochenkov: So, after we run the macro's expander function and got a +piece of AST (or got tokens and parsed them into a piece of AST) we need to +integrate that piece of AST into the big existing partially built AST. + +Vadim Petrochenkov: This integration is a really important step where the next +things happen: +- NodeIds are assigned. + + Vadim Petrochenkov: "def paths"s and their IDs (DefIds) are created + + Vadim Petrochenkov: Names are put into modules from the resolver point of + view. + +Vadim Petrochenkov: So, we are basically turning some vague token-like mass +into proper set in stone hierarhical AST and side tables. + +Vadim Petrochenkov: Where exactly this happens - NodeIds are assigned by +InvocationCollector (which also collects new macro calls from this new AST +piece and adds them to the queue), DefIds are created by DefCollector, and +modules are filled by BuildReducedGraphVisitor. + +Vadim Petrochenkov: These three passes run one after another on every AST +fragment freshly expanded from a macro. + +Vadim Petrochenkov: After expanding a single macro and integrating its output +we again try to resolve all imports in the crate, and then return to the big +queue processing loop and pick up the next macro. + +Vadim Petrochenkov: Repeat until there's no more macros. Vadim Petrochenkov: + +mark-i-m: The integration step is where we would get parser errors too right? + +mark-i-m: Also, when do we know definitively that resolution has failed for +particular ident? + + Vadim Petrochenkov: + + The integration step is where we would get parser errors too right? + +Yes, if the macro produced tokens (rather than AST directly) and we had to +parse them. + + Vadim Petrochenkov: + + when do we know definitively that resolution has failed for particular + ident? + +So, ident is looked up in a number of scopes during resolution. From closest +like the current block or module, to far away like preludes or built-in types. + +Vadim Petrochenkov: If lookup is certainly failed in all of the scopes, then +it's certainly failed. + +mark-i-m: This is after all expansions and integrations are done, right? + +Vadim Petrochenkov: "Certainly" is determined differently for different scopes, +e.g. for a module scope it means no unexpanded macros and no unresolved glob +imports in that module. + + Vadim Petrochenkov: + + This is after all expansions and integrations are done, right? + +For macro and import names this happens during expansions and integrations. + +mark-i-m: Makes sense + +Vadim Petrochenkov: For all other names we certainly know whether a name is +resolved successfully or not on the first attempt, because no new names can +appear. + +Vadim Petrochenkov: (They are resolved in a later pass, see +librustc_resolve/late.rs.) + +mark-i-m: And if at the end of the iteration, there are still things in the +queue that can't be resolve, this represents an error, right? + +mark-i-m: i.e. an undefined macro? + +Vadim Petrochenkov: Yes, if we make no progress during an iteration, then we +are stuck and that state represent an error. + +Vadim Petrochenkov: We attempt to recover though, using dummies expanding into +nothing or ExprKind::Err or something like that for unresolved macros. + +mark-i-m: This is for the purposes of diagnostics, though, right? + +Vadim Petrochenkov: But if we are going through recovery, then compilation must +result in an error anyway. + +Vadim Petrochenkov: Yes, that's for diagnostics, without recovery we would +stuck at the first unresolved macro or import. Vadim Petrochenkov: + +So, about the SyntaxContext hygiene... + +Vadim Petrochenkov: New syntax contexts are created during macro expansion. + +Vadim Petrochenkov: If the token had context X before being produced by a +macro, e.g. here ident has context SyntaxContext::root(): Vadim Petrochenkov: + +macro m() { ident } + +Vadim Petrochenkov: , then after being produced by the macro it has context X +-> macro_id. + +Vadim Petrochenkov: I.e. our ident has context ROOT -> id(m) after it's +produced by m. + +Vadim Petrochenkov: The "chaining operator" -> is apply_mark in compiler code. +Vadim Petrochenkov: + +macro m() { macro n() { ident } } + +Vadim Petrochenkov: In this example the ident has context ROOT originally, then +ROOT -> id(m), then ROOT -> id(m) -> id(n). + +Vadim Petrochenkov: Note that these chains are not entirely determined by their +last element, in other words ExpnId is not isomorphic to SyntaxCtxt. + +Vadim Petrochenkov: Couterexample: Vadim Petrochenkov: + +macro m($i: ident) { macro n() { ($i, bar) } } + +m!(foo); + +Vadim Petrochenkov: foo has context ROOT -> id(n) and bar has context ROOT -> +id(m) -> id(n) after all the expansions. + +mark-i-m: Cool :) + +mark-i-m: It looks like we are out of time + +mark-i-m: Is there anything you wanted to add? + +mark-i-m: We can schedule another meeting if you would like + +Vadim Petrochenkov: Yep, 23.06 already. No, I think this is an ok point to +stop. + +mark-i-m: :+1: + +mark-i-m: Thanks @Vadim Petrochenkov ! This was very helpful + +Vadim Petrochenkov: Yeah, we can schedule another one. So far it's been like 1 +hour of meetings per month? Certainly not a big burden. +``` diff --git a/src/doc/rustc-guide/src/mir/construction.md b/src/doc/rustc-guide/src/mir/construction.md index 0e0bf35e73..35d68ad73a 100644 --- a/src/doc/rustc-guide/src/mir/construction.md +++ b/src/doc/rustc-guide/src/mir/construction.md @@ -92,7 +92,7 @@ There are essentially four kinds of representations one might want of an express * `Operand` is an argument to e.g. a `+` operation or a function call * a temporary variable containing a copy of the value -These following image depicts a general overview of the interactions between the +The following image depicts a general overview of the interactions between the representations: diff --git a/src/doc/rustc-guide/src/mir/index.md b/src/doc/rustc-guide/src/mir/index.md index 9e9f933fe8..c02b86e9a1 100644 --- a/src/doc/rustc-guide/src/mir/index.md +++ b/src/doc/rustc-guide/src/mir/index.md @@ -18,7 +18,7 @@ graphs and desugaring), you may enjoy the MIR is defined in the [`src/librustc/mir/`][mir] module, but much of the code that manipulates it is found in [`src/librustc_mir`][mirmanip]. -[RFC 1211]: http://rust-lang.github.io/rfcs/1211-mir.html +[RFC 1211]: https://rust-lang.github.io/rfcs/1211-mir.html Some of the key characteristics of MIR are: @@ -185,7 +185,7 @@ only reference places and constants. Moreover, when you use a place, we indicate whether we are **copying it** (which requires that the place have a type `T` where `T: Copy`) or **moving it** (which works for a place of any type). So, for example, if we had the expression `x -= a + b + c` in Rust, that would get compile to two statements and a += a + b + c` in Rust, that would get compiled to two statements and a temporary: ```mir diff --git a/src/doc/rustc-guide/src/mir/optimizations.md b/src/doc/rustc-guide/src/mir/optimizations.md index ddafa0c99c..f3fdd52f31 100644 --- a/src/doc/rustc-guide/src/mir/optimizations.md +++ b/src/doc/rustc-guide/src/mir/optimizations.md @@ -1 +1,49 @@ # MIR optimizations + +MIR optimizations are optimizations run on the [MIR][mir] to produce better MIR +before codegen. This is important for two reasons: first, it makes the final +generated executable code better, and second, it means that LLVM has less work +to do, so compilation is faster. Note that since MIR is generic (not +[monomorphized][monomorph] yet), these optimizations are particularly +effective; we can optimize the generic version, so all of the monomorphizations +are cheaper! + +[mir]: https://rust-lang.github.io/rustc-guide/mir/index.html +[monomorph]: https://rust-lang.github.io/rustc-guide/appendix/glossary.html?highlight=monomorphize#appendix-c-glossary + +MIR optimizations run after borrow checking. We run a series of optimization +passes over the MIR to improve it. Some passes are required to run on all code, +some passes don't actually do optimizations but only check stuff, and some +passes are only turned on in `release` mode. + +The [`optimized_mir`][optmir] [query] is called to produce the optimized MIR +for a given [`DefId`][defid]. This query makes sure that the borrow checker has +run and that some validation has occurred. Then, it [steals][steal] the MIR +optimizes it, and returns the improved MIR. + +[optmir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.optimized_mir.html +[query]: https://rust-lang.github.io/rustc-guide/query.html +[defid]: https://rust-lang.github.io/rustc-guide/appendix/glossary.html?highlight=DefId#appendix-c-glossary +[steal]: https://rust-lang.github.io/rustc-guide/mir/passes.html?highlight=steal#stealing + +## Defining optimization passes + +The list of passes run and the order in which they are run is defined by the +[`run_optimization_passes`][rop] function. It contains an array of passes to +run. Each pass in the array is a struct that implements the [`MirPass`] trait. +The array is an array of `&dyn MirPass` trait objects. Typically, a pass is +implemented in its own submodule of the [`rustc_mir::transform`][trans] module. + +[rop]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.run_optimization_passes.html +[`MirPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/trait.MirPass.html +[trans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/index.html + +Some examples of passes are: +- `CleanupNonCodegenStatements`: remove some of the info that is only needed for + analyses, rather than codegen. +- `ConstProp`: Does [constant propagation][constprop] + +You can see the ["Implementors" section of the `MirPass` rustdocs][impl] for more examples. + +[impl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/trait.MirPass.html#implementors +[constprop]: https://en.wikipedia.org/wiki/Constant_folding#Constant_propagation diff --git a/src/doc/rustc-guide/src/mir/passes.md b/src/doc/rustc-guide/src/mir/passes.md index a0de3ae0e4..b847584b1b 100644 --- a/src/doc/rustc-guide/src/mir/passes.md +++ b/src/doc/rustc-guide/src/mir/passes.md @@ -27,7 +27,7 @@ where we want to access the MIR for type checking or other purposes: A `MirPass` is some bit of code that processes the MIR, typically – but not always – transforming it along the way somehow. For example, it might perform an optimization. The `MirPass` trait itself is found -in in [the `rustc_mir::transform` module][mirtransform], and it +in [the `rustc_mir::transform` module][mirtransform], and it basically consists of one method, `run_pass`, that simply gets an `&mut Mir` (along with the tcx and some information about where it came from). The MIR is therefore modified in place (which helps to diff --git a/src/doc/rustc-guide/src/miri.md b/src/doc/rustc-guide/src/miri.md index aee2376f1b..09c31e0a5c 100644 --- a/src/doc/rustc-guide/src/miri.md +++ b/src/doc/rustc-guide/src/miri.md @@ -55,50 +55,87 @@ Before the evaluation, a virtual memory location (in this case essentially a `vec![u8; 4]` or `vec![u8; 8]`) is created for storing the evaluation result. At the start of the evaluation, `_0` and `_1` are -`ConstValue::Scalar(Scalar::Undef)`. When the initialization of `_1` is invoked, the -value of the `FOO` constant is required, and triggers another call to -`tcx.const_eval`, which will not be shown here. If the evaluation of FOO is -successful, 42 will be subtracted by its value `4096` and the result stored in -`_1` as `ConstValue::ScalarPair(Scalar::Bytes(4054), Scalar::Bytes(0))`. The first -part of the pair is the computed value, the second part is a bool that's true if -an overflow happened. +`Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef))`. This is quite +a mouthful: [`Operand`] can represent either data stored somewhere in the +[interpreter memory](#memory) (`Operand::Indirect`), or (as an optimization) +immediate data stored in-line. And [`Immediate`] can either be a single +(potentially uninitialized) [scalar value][`Scalar`] (integer or thin pointer), +or a pair of two of them. In our case, the single scalar value is *not* (yet) +initialized. + +When the initialization of `_1` is invoked, the value of the `FOO` constant is +required, and triggers another call to `tcx.const_eval`, which will not be shown +here. If the evaluation of FOO is successful, `42` will be subtracted from its +value `4096` and the result stored in `_1` as +`Operand::Immediate(Immediate::ScalarPair(Scalar::Raw { data: 4054, .. }, +Scalar::Raw { data: 0, .. })`. The first part of the pair is the computed value, +the second part is a bool that's true if an overflow happened. A `Scalar::Raw` +also stores the size (in bytes) of this scalar value; we are eliding that here. The next statement asserts that said boolean is `0`. In case the assertion fails, its error message is used for reporting a compile-time error. -Since it does not fail, `ConstValue::Scalar(Scalar::Bytes(4054))` is stored in the -virtual memory was allocated before the evaluation. `_0` always refers to that -location directly. - -After the evaluation is done, the virtual memory allocation is interned into the -`TyCtxt`. Future evaluations of the same constants will not actually invoke -miri, but just extract the value from the interned allocation. - -The `tcx.const_eval` function has one additional feature: it will not return a -`ByRef(interned_allocation_id)`, but a `Scalar(computed_value)` if possible. This -makes using the result much more convenient, as no further queries need to be -executed in order to get at something as simple as a `usize`. +Since it does not fail, `Operand::Immediate(Immediate::Scalar(Scalar::Raw { +data: 4054, .. }))` is stored in the virtual memory was allocated before the +evaluation. `_0` always refers to that location directly. + +After the evaluation is done, the return value is converted from [`Operand`] to +[`ConstValue`] by [`op_to_const`]: the former representation is geared towards +what is needed *during* cost evaluation, while [`ConstValue`] is shaped by the +needs of the remaining parts of the compiler that consume the results of const +evaluation. As part of this conversion, for types with scalar values, even if +the resulting [`Operand`] is `Indirect`, it will return an immediate +`ConstValue::Scalar(computed_value)` (instead of the usual `ConstValue::ByRef`). +This makes using the result much more efficient and also more convenient, as no +further queries need to be executed in order to get at something as simple as a +`usize`. + +Future evaluations of the same constants will not actually invoke +Miri, but just use the cached result. + +[`Operand`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/enum.Operand.html +[`Immediate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/enum.Immediate.html +[`ConstValue`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/interpret/enum.ConstValue.html +[`Scalar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/interpret/enum.Scalar.html +[`op_to_const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/const_eval/fn.op_to_const.html ## Datastructures -Miri's core datastructures can be found in +Miri's outside-facing datastructures can be found in [librustc/mir/interpret](https://github.com/rust-lang/rust/blob/master/src/librustc/mir/interpret). -This is mainly the error enum and the `ConstValue` and `Scalar` types. A `ConstValue` can -be either `Scalar` (a single `Scalar`), `ScalarPair` (two `Scalar`s, usually fat -pointers or two element tuples) or `ByRef`, which is used for anything else and -refers to a virtual allocation. These allocations can be accessed via the -methods on `tcx.interpret_interner`. - -If you are expecting a numeric result, you can use `unwrap_usize` (panics on -anything that can't be representad as a `u64`) or `assert_usize` which results -in an `Option` yielding the `Scalar` if possible. - -## Allocations - -A miri allocation is either a byte sequence of the memory or an `Instance` in -the case of function pointers. Byte sequences can additionally contain -relocations that mark a group of bytes as a pointer to another allocation. The -actual bytes at the relocation refer to the offset inside the other allocation. +This is mainly the error enum and the [`ConstValue`] and [`Scalar`] types. A +`ConstValue` can be either `Scalar` (a single `Scalar`, i.e., integer or thin +pointer), `Slice` (to represent byte slices and strings, as needed for pattern +matching) or `ByRef`, which is used for anything else and refers to a virtual +allocation. These allocations can be accessed via the methods on +`tcx.interpret_interner`. A `Scalar` is either some `Raw` integer or a pointer; +see [the next section](#memory) for more on that. + +If you are expecting a numeric result, you can use `eval_usize` (panics on +anything that can't be representad as a `u64`) or `try_eval_usize` which results +in an `Option` yielding the `Scalar` if possible. + +## Memory + +To support any kind of pointers, Miri needs to have a "virtual memory" that the +pointers can point to. This is implemented in the [`Memory`] type. In the +simplest model, every global variable, stack variable and every dynamic +allocation corresponds to an [`Allocation`] in that memory. (Actually using an +allocation for every MIR stack variable would be very inefficient; that's why we +have `Operand::Immediate` for stack variables that are both small and never have +their address taken. But that is purely an optimization.) + +Such an `Allocation` is basically just a sequence of `u8` storing the value of +each byte in this allocation. (Plus some extra data, see below.) Every +`Allocation` has a globally unique `AllocId` assigned in `Memory`. With that, a +[`Pointer`] consists of a pair of an `AllocId` (indicating the allocation) and +an offset into the allocation (indicating which byte of the allocation the +pointer points to). It may seem odd that a `Pointer` is not just an integer +address, but remember that during const evaluation, we cannot know at which +actual integer address the allocation will end up -- so we use `AllocId` as +symbolic base addresses, which means we need a separate offset. (As an aside, +it turns out that pointers at run-time are +[more than just integers, too](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#pointer-provenance).) These allocations exist so that references and raw pointers have something to point to. There is no global linear heap in which things are allocated, but each @@ -106,7 +143,60 @@ allocation (be it for a local variable, a static or a (future) heap allocation) gets its own little memory with exactly the required size. So if you have a pointer to an allocation for a local variable `a`, there is no possible (no matter how unsafe) operation that you can do that would ever change said pointer -to a pointer to `b`. +to a pointer to a different local variable `b`. +Pointer arithmetic on `a` will only ever change its offset; the `AllocId` stays the same. + +This, however, causes a problem when we want to store a `Pointer` into an +`Allocation`: we cannot turn it into a sequence of `u8` of the right length! +`AllocId` and offset together are twice as big as a pointer "seems" to be. This +is what the `relocation` field of `Allocation` is for: the byte offset of the +`Pointer` gets stored as a bunch of `u8`, while its `AllocId` gets stored +out-of-band. The two are reassembled when the `Pointer` is read from memory. +The other bit of extra data an `Allocation` needs is `undef_mask` for keeping +track of which of its bytes are initialized. + +### Global memory and exotic allocations + +`Memory` exists only during the Miri evaluation; it gets destroyed when the +final value of the constant is computed. In case that constant contains any +pointers, those get "interned" and moved to a global "const eval memory" that is +part of `TyCtxt`. These allocations stay around for the remaining computation +and get serialized into the final output (so that dependent crates can use +them). + +Moreover, to also support function pointers, the global memory in `TyCtxt` can +also contain "virtual allocations": instead of an `Allocation`, these contain an +`Instance`. That allows a `Pointer` to point to either normal data or a +function, which is needed to be able to evaluate casts from function pointers to +raw pointers. + +Finally, the [`GlobalAlloc`] type used in the global memory also contains a +variant `Static` that points to a particular `const` or `static` item. This is +needed to support circular statics, where we need to have a `Pointer` to a +`static` for which we cannot yet have an `Allocation` as we do not know the +bytes of its value. + +[`Memory`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/interpret/struct.Memory.html +[`Allocation`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/interpret/struct.Allocation.html +[`Pointer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/interpret/struct.Pointer.html +[`GlobalAlloc`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/interpret/enum.GlobalAlloc.html + +### Pointer values vs Pointer types + +One common cause of confusion in Miri is that being a pointer *value* and having +a pointer *type* are entirely independent properties. By "pointer value", we +refer to a `Scalar::Ptr` containing a `Pointer` and thus pointing somewhere into +Miri's virtual memory. This is in contrast to `Scalar::Raw`, which is just some +concrete integer. + +However, a variable of pointer or reference *type*, such as `*const T` or `&T`, +does not have to have a pointer *value*: it could be obtaining by casting or +transmuting an integer to a pointer (currently that is hard to do in const eval, +but eventually `transmute` will be stable as a `const fn`). And similarly, when +casting or transmuting a reference to some actual allocation to an integer, we +end up with a pointer *value* (`Scalar::Ptr`) at integer *type* (`usize`). This +is a problem because we cannot meaningfully perform integer operations such as +division on pointer values. ## Interpretation diff --git a/src/doc/rustc-guide/src/profiling/with_perf.md b/src/doc/rustc-guide/src/profiling/with_perf.md index 7582eece56..cca2d06d13 100644 --- a/src/doc/rustc-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-guide/src/profiling/with_perf.md @@ -14,7 +14,7 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or - Make a rustup toolchain pointing to that result - see [the "build and run" section for instructions][b-a-r] -[b-a-r]: ../how-to-build-and-run.html#toolchain +[b-a-r]: ../building/how-to-build-and-run.html#toolchain ## Gathering a perf profile @@ -28,7 +28,7 @@ of events, though, like cache misses and so forth. The basic `perf` command is this: ```bash -> perf record -F99 --call-graph dwarf XXX +perf record -F99 --call-graph dwarf XXX ``` The `-F99` tells perf to sample at 99 Hz, which avoids generating too @@ -39,7 +39,7 @@ information from debuginfo, which is accurate. The `XXX` is the command you want to profile. So, for example, you might do: ```bash -> perf record -F99 --call-graph dwarf cargo + rustc +perf record -F99 --call-graph dwarf cargo + rustc ``` to run `cargo` -- here `` should be the name of the toolchain @@ -59,7 +59,7 @@ do that, the first step is to clone [the rustc-perf repository][rustc-perf-gh]: ```bash -> git clone https://github.com/rust-lang-nursery/rustc-perf +git clone https://github.com/rust-lang-nursery/rustc-perf ``` [rustc-perf-gh]: https://github.com/rust-lang-nursery/rustc-perf @@ -75,13 +75,13 @@ do profiling for you! You can find For example, to measure the clap-rs test, you might do: ```bash -> ./target/release/collector - --output-repo /path/to/place/output - profile perf-record - --rustc /path/to/rustc/executable/from/your/build/directory - --cargo `which cargo` - --filter clap-rs - --builds Check +./target/release/collector \ + --output-repo /path/to/place/output \ + profile perf-record \ + --rustc /path/to/rustc/executable/from/your/build/directory \ + --cargo `which cargo` \ + --filter clap-rs \ + --builds Check \ ``` You can also use that same command to use cachegrind or other profiling tools. @@ -97,7 +97,7 @@ example: [dir]: https://github.com/rust-lang-nursery/rustc-perf/tree/master/collector/benchmarks ```bash -> cd collector/benchmarks/clap-rs +cd collector/benchmarks/clap-rs ``` In this case, let's say we want to profile the `cargo check` @@ -106,8 +106,8 @@ build the dependencies: ```bash # Setup: first clean out any old results and build the dependencies: -> cargo + clean -> CARGO_INCREMENTAL=0 cargo + check +cargo + clean +CARGO_INCREMENTAL=0 cargo + check ``` (Again, `` should be replaced with the name of the @@ -118,8 +118,8 @@ running cargo check. I tend to use `cargo rustc` for this, since it also allows me to add explicit flags, which we'll do later on. ```bash -> touch src/lib.rs -> CARGO_INCREMENTAL=0 perf record -F99 --call-graph dwarf cargo rustc --profile check --lib +touch src/lib.rs +CARGO_INCREMENTAL=0 perf record -F99 --call-graph dwarf cargo rustc --profile check --lib ``` Note that final command: it's a doozy! It uses the `cargo rustc` @@ -130,7 +130,7 @@ the `--profile check` and `--lib` options specify that we are doing a At this point, we can use `perf` tooling to analyze the results. For example: ```bash -> perf report +perf report ``` will open up an interactive TUI program. In simple cases, that can be @@ -149,8 +149,8 @@ If you want to profile an NLL run, you can just pass extra options to the `cargo rustc` command, like so: ```bash -> touch src/lib.rs -> CARGO_INCREMENTAL=0 perf record -F99 --call-graph dwarf cargo rustc --profile check --lib -- -Zborrowck=mir +touch src/lib.rs +CARGO_INCREMENTAL=0 perf record -F99 --call-graph dwarf cargo rustc --profile check --lib -- -Zborrowck=mir ``` [pf]: https://github.com/nikomatsakis/perf-focus @@ -180,7 +180,7 @@ would analyze NLL performance. You can install perf-focus using `cargo install`: ```bash -> cargo install perf-focus +cargo install perf-focus ``` ### Example: How much time is spent in MIR borrowck? @@ -191,7 +191,7 @@ function of the MIR borrowck is called `do_mir_borrowck`, so we can do this command: ```bash -> perf focus '{do_mir_borrowck}' +$ perf focus '{do_mir_borrowck}' Matcher : {do_mir_borrowck} Matches : 228 Not Matches: 542 @@ -216,7 +216,7 @@ samples where `do_mir_borrowck` was on the stack: in this case, 29%. by doing: ```bash -> perf script | c++filt | perf focus --from-stdin ... +perf script | c++filt | perf focus --from-stdin ... ``` This will pipe the output from `perf script` through `c++filt` and @@ -232,7 +232,7 @@ Perhaps we'd like to know how much time MIR borrowck spends in the trait checker. We can ask this using a more complex regex: ```bash -> perf focus '{do_mir_borrowck}..{^rustc::traits}' +$ perf focus '{do_mir_borrowck}..{^rustc::traits}' Matcher : {do_mir_borrowck},..{^rustc::traits} Matches : 12 Not Matches: 1311 @@ -260,7 +260,7 @@ usually also want to give `--tree-min-percent` or `--tree-max-depth`. The result looks like this: ```bash -> perf focus '{do_mir_borrowck}' --tree-callees --tree-min-percent 3 +$ perf focus '{do_mir_borrowck}' --tree-callees --tree-min-percent 3 Matcher : {do_mir_borrowck} Matches : 577 Not Matches: 746 @@ -311,7 +311,7 @@ could get our percentages relative to the borrowck itself like so: ```bash -> perf focus '{do_mir_borrowck}' --tree-callees --relative --tree-max-depth 1 --tree-min-percent 5 +$ perf focus '{do_mir_borrowck}' --tree-callees --relative --tree-max-depth 1 --tree-min-percent 5 Matcher : {do_mir_borrowck} Matches : 577 Not Matches: 746 diff --git a/src/doc/rustc-guide/src/rustc-driver.md b/src/doc/rustc-guide/src/rustc-driver.md index 715e6295d4..eb5390a920 100644 --- a/src/doc/rustc-guide/src/rustc-driver.md +++ b/src/doc/rustc-guide/src/rustc-driver.md @@ -9,17 +9,18 @@ for running code at particular times during the compilation process, allowing third parties to effectively use `rustc`'s internals as a library for analysing a crate or emulating the compiler in-process (e.g. the RLS or rustdoc). -For those using `rustc` as a library, the `interface::run_compiler()` function is the main -entrypoint to the compiler. It takes a configuration for the compiler and a closure that -takes a [`Compiler`]. `run_compiler` creates a `Compiler` from the configuration and passes -it to the closure. Inside the closure, you can use the `Compiler` to drive queries to compile -a crate and get the results. This is what the `rustc_driver` does too. +For those using `rustc` as a library, the [`rustc_interface::interface::run_compiler()`][i_rc] +function is the main entrypoint to the compiler. It takes a configuration for the compiler +and a closure that takes a [`Compiler`]. `run_compiler` creates a `Compiler` from the +configuration and passes it to the closure. Inside the closure, you can use the `Compiler` +to drive queries to compile a crate and get the results. This is what the `rustc_driver` does too. You can see what queries are currently available through the rustdocs for [`Compiler`]. You can see an example of how to use them by looking at the `rustc_driver` implementation, specifically the [`rustc_driver::run_compiler` function][rd_rc] (not to be confused with -`interface::run_compiler`). The `rustc_driver::run_compiler` function takes a bunch of -command-line args and some other configurations and drives the compilation to completion. +[`rustc_interface::interface::run_compiler`][i_rc]). The `rustc_driver::run_compiler` function +takes a bunch of command-line args and some other configurations and +drives the compilation to completion. `rustc_driver::run_compiler` also takes a [`Callbacks`][cb]. In the past, when the `rustc_driver::run_compiler` was the primary way to use the compiler as a @@ -47,10 +48,11 @@ thread-locals, although you should rarely need to touch it. [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html [rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html +[i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html [`rustc_driver`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/ [`Compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html -[`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html +[`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TyCtxt.html [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html [stupid-stats]: https://github.com/nrc/stupid-stats diff --git a/src/doc/rustc-guide/src/salsa.md b/src/doc/rustc-guide/src/salsa.md new file mode 100644 index 0000000000..b34647ad1e --- /dev/null +++ b/src/doc/rustc-guide/src/salsa.md @@ -0,0 +1,214 @@ +# How Salsa works + +This chapter is based on the explanation given by Niko Matsakis in this +[video](https://www.youtube.com/watch?v=_muY4HjSqVw) about +[Salsa](https://github.com/salsa-rs/salsa). + +> Salsa is not used directly in rustc, but it is used extensively for +> rust-analyzer and may be integrated into the compiler in the future. + +## What is Salsa? + +Salsa is a library for incremental recomputation, this means reusing +computation that has already been done in the past to increase the efficiency +of future computations. + +The objectives of Salsa are: + * Provide that functionality in an automatic way, so reusing old computations + is done automatically by the library + * Doing so in a "sound", or "correct", way, therefore leading to the same + results as if it had been done from scratch + +Salsa's actual model is much richer, allowing many kinds of inputs and many +different outputs. +For example, integrating Salsa with an IDE could mean that the inputs could be +the manifest (`Cargo.toml`), entire source files (`foo.rs`), snippets and so +on; the outputs of such an integration could range from a binary executable, to +lints, types (for example, if a user selects a certain variable and wishes to +see its type), completions, etc. + +## How does it work? + +The first thing that Salsa has to do is identify the "base inputs" [^EN1]. + +Then Salsa has to also identify intermediate, "derived" values, which are +something that the library produces, but, for each derived value there's a +"pure" function that computes the derived value. + +For example, there might be a function `ast(x: Path) -> AST`. The produced +`AST` isn't a final value, it's an intermidiate value that the library would +use for the computation. + +This means that when you try to compute with the library, Salsa is going to +compute various derived values, and eventually read the input and produce the +result for the asked computation. + +In the course of computing, Salsa tracks which inputs were accessed and which +values are derived. This information is used to determine what's going to +happen when the inputs change: are the derived values still valid? + +This doesn't necessarily mean that each computation downstream from the input +is going to be checked, which could be costly. Salsa only needs to check each +downstream computation until it finds one that isn't changed. At that point, it +won't check other derived computations since they wouldn't need to change. + +It's is helpful to think about this as a graph with nodes. Each derived value +has a dependency on other values, which could themselves be either base or +derived. Base values don't have a dependency. + +```ignore +I <- A <- C ... + | +J <- B <--+ +``` + +When an input `I` changes, the derived value `A` could change. The derived +value `B` , which does not depend on `I`, `A`, or any value derived from `A` or +`I`, is not subject to change. Therefore, Salsa can reuse the computation done +for `B` in the past, without having to compute it again. + +The computation could also terminate early. Keeping the same graph as before, +say that input `I` has changed in some way (and input `J` hasn't) but, when +computing `A` again, it's found that `A` hasn't changed from the previous +computation. This leads to an "early termination", because there's no need to +check if `C` needs to change, since both `C` direct inputs, `A` and `B`, +haven't changed. + +## Key Salsa concepts + +### Query + +A query is some value that Salsa can access in the course of computation. Each +query can have a number of keys (from 0 to many), and all queries have a +result, akin to functions. 0-key queries are called "input" queries. + +### Database + +The database is basically the context for the entire computation, it's meant to +store Salsa's internal state, all intermediate values for each query, and +anything else that the computation might need. The database must know all the +queries that the library is going to do before it can be built, but they don't +need to be specified in the same place. + +After the database is formed, it can be accessed with queries that are very +similar to functions. Since each query's result is stored in the database, +when a query is invoked N times, it will return N **cloned** results, without +having to recompute the query (unless the input has changed in such a way that +it warrants recomputation). + +For each input query (0-key), a "set" method is generated, allowing the user to +change the output of such query, and trigger previous memoized values to be +potentially invalidated. + +### Query Groups + +A query group is a set of queries which have been defined together as a unit. +The database is formed by combining query groups. Query groups are akin to +"Salsa modules" [^EN2]. + +A set of queries in a query group are just a set of methods in a trait. + +To create a query group a trait annotated with a specific attribute +(`#[salsa::query_group(...)]`) has to be created. + +An argument must also be provided to said attribute as it will be used by Salsa +to create a struct to be used later when the database is created. + +Example input query group: + +```rust,ignore +/// This attribute will process this tree, produce this tree as output, and produce +/// a bunch of intermidiate stuff that Salsa also uses. One of these things is a +/// "StorageStruct", whose name we have specified in the attribute. +/// +/// This query group is a bunch of **input** queries, that do not rely on any +/// derived input. +#[salsa::query_group(InputsStorage)] +pub trait Inputs { + /// This attribute (`#[salsa::input]`) indicates that this query is a base + /// input, therefore `set_manifest` is going to be auto-generated + #[salsa::input] + fn manifest(&self) -> Manifest; + + #[salsa::input] + fn source_text(&self, name: String) -> String; +} +``` + +To create a **derived** query group, one must specify which other query groups +this one depends on by specifying them as supertraits, as seen in the following +example: + +```rust,ignore +/// This query group is going to contain queries that depend on derived values a +/// query group can access another query group's queries by specifying the +/// dependency as a super trait query groups can be stacked as much as needed using +/// that pattern. +#[salsa::query_group(ParserStorage)] +pub trait Parser: Inputs { + /// This query `ast` is not an input query, it's a derived query this means + /// that a definition is necessary. + fn ast(&self, name: String) -> String; +} +``` + +When creating a derived query the implementation of said query must be defined +outside the trait. The definition must take a database parameter as an `impl +Trait` (or `dyn Trait`), where `Trait` is the query group that the definition +belongs to, in addition to the other keys. + +```rust,ignore +///This is going to be the definition of the `ast` query in the `Parser` trait. +///So, when the query `ast` is invoked, and it needs to be recomputed, Salsa is going to call this function +///and it's is going to give it the database as `impl Parser`. +///The function doesn't need to be aware of all the queries of all the query groups +fn ast(db: &impl Parser, name: String) -> String { + //! Note, `impl Parser` is used here but `dyn Parser` works just as well + /* code */ + ///By passing an `impl Parser`, this is allowed + let source_text = db.input_file(name); + /* do the actual parsing */ + return ast; +} +``` + +Eventually, after all the query groups have been defined, the database can be +created by declaring a struct. + +To specify which query groups are going to be part of the database an attribute +(`#[salsa::database(...)]`) must be added. The argument of said attribute is a +list of identifiers, specifying the query groups **storages**. + +```rust,ignore +///This attribute specifies which query groups are going to be in the database +#[salsa::database(InputsStorage, ParserStorage)] +#[derive(Default)] //optional! +struct MyDatabase { + ///You also need this one field + runtime : salsa::Runtime, +} +///And this trait has to be implemented +impl salsa::Databse for MyDatabase { + fn salsa_runtime(&self) -> &salsa::Runtime { + &self.runtime + } +} +``` + +Example usage: + +```rust,ignore +fn main() { + let db = MyDatabase::default(); + db.set_manifest(...); + db.set_source_text(...); + loop { + db.ast(...); //will reuse results + db.set_source_text(...); + } +} +``` + +[^EN1]: "They are not something that you **inaubible** but something that you kinda get **inaudible** from the outside [3:23](https://youtu.be/_muY4HjSqVw?t=203). + +[^EN2]: What is a Salsa module? diff --git a/src/doc/rustc-guide/src/sanitizers.md b/src/doc/rustc-guide/src/sanitizers.md new file mode 100644 index 0000000000..6205433e59 --- /dev/null +++ b/src/doc/rustc-guide/src/sanitizers.md @@ -0,0 +1,68 @@ +# Sanitizers Support + +The rustc compiler contains basic support for following sanitizers: + +* [AddressSanitizer][clang-asan] a faster memory error detector. Can + detect out-of-bounds access to heap, stack, and globals, use after free, use + after return, double free, invalid free, memory leaks. +* [LeakSanitizer][clang-lsan] a run-time memory leak detector. +* [MemorySanitizer][clang-msan] a detector of uninitialized reads. +* [ThreadSanitizer][clang-tsan] a fast data race detector. + +## How to use the sanitizers? + +To enable a sanitizer compile with `-Zsanitizer=...` option, where value is one +of `address`, `leak`, `memory` or `thread`. For more details how to use +sanitizers please refer to [the unstable book](https://doc.rust-lang.org/unstable-book/). + +## How are sanitizers implemented in rustc? + +The implementation of sanitizers relies entirely on LLVM. It consists of +compile time instrumentation passes and runtime libraries. The role rustc plays +in the implementation is limited to the execution of the following steps: + +1. The sanitizer runtime libraries are part of the [compiler-rt] project, and + [will be built as an LLVM subproject][sanitizer-build] when enabled in + `config.toml`: + + ```toml + [build] + sanitizers = true + ``` + + The runtimes are [placed into target libdir][sanitizer-copy]. + +2. During LLVM code generation, the functions intended for instrumentation are + [marked][sanitizer-attribute] with `SanitizeAddress`, `SanitizeMemory`, or + `SanitizeThread` attribute. Currently those attributes are applied in + indiscriminate manner. but in principle they could be used to perform + instrumentation selectively. + +3. The LLVM IR generated by rustc is instrumented by [dedicated LLVM + passes][sanitizer-pass], different for each sanitizer. Instrumentation + passes are invoked after optimization passes. + +4. When producing an executable, the sanitizer specific runtime library is + [linked in][sanitizer-link]. The libraries are searched for in target libdir + relative to default system root, so that this process is not affected + by sysroot overrides used for example by cargo `-Zbuild-std` functionality. + +[compiler-rt]: https://github.com/llvm/llvm-project/tree/master/compiler-rt +[sanitizer-build]: https://github.com/rust-lang/rust/blob/87c3eedffba64830b67e54e75dd479f9fd83cc7d/src/bootstrap/native.rs#L220-L225 +[sanitizer-copy]: https://github.com/rust-lang/rust/blob/87c3eedffba64830b67e54e75dd479f9fd83cc7d/src/bootstrap/compile.rs#L269-L321 +[sanitizer-attribute]: https://github.com/rust-lang/rust/blob/1.38.0/src/librustc_codegen_llvm/declare.rs#L53-L66 +[sanitizer-pass]: https://github.com/rust-lang/rust/blob/1.38.0/src/librustc_codegen_ssa/back/write.rs#L406-L420 +[sanitizer-link]: https://github.com/rust-lang/rust/blob/87c3eedffba64830b67e54e75dd479f9fd83cc7d/src/librustc_codegen_ssa/back/link.rs#L729-L770 + +## Additional Information + +* [Sanitizers project page](https://github.com/google/sanitizers/wiki/) +* [AddressSanitizer in Clang][clang-asan] +* [LeakSanitizer in Clang][clang-lsan] +* [MemorySanitizer in Clang][clang-msan] +* [ThreadSanitizer in Clang][clang-tsan] + +[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html +[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html +[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html +[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html diff --git a/src/doc/rustc-guide/src/stability.md b/src/doc/rustc-guide/src/stability.md index 46f62e5203..1db738cb2f 100644 --- a/src/doc/rustc-guide/src/stability.md +++ b/src/doc/rustc-guide/src/stability.md @@ -3,13 +3,18 @@ This section is about the stability attributes and schemes that allow stable APIs to use unstable APIs internally in the rustc standard library. -For instructions on stabilizing a language feature see +For instructions on stabilizing a language feature see [Stabilizing Features](./stabilization_guide.md). -# unstable +## unstable The `#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]` attribute explicitly -marks an item as unstable. This infects all sub-items, where the attribute doesn't have to be +marks an item as unstable. Items that are marked as "unstable" cannot be used +without a corresponding `#![feature]` attribute on the crate, even on a +nightly compiler. This restriction only applies across crate boundaries, unstable +items may be used within the crate they are defined. + +The `unstable` attribute infects all sub-items, where the attribute doesn't have to be reapplied. So if you apply this to a module, all items in the module will be unstable. You can make specific sub-items stable by using the `#[stable]` attribute on them. @@ -21,9 +26,14 @@ Note, however, that due to a [rustc bug], stable items inside unstable modules can import `core::intrinsics::transmute` even though `intrinsics` is an unstable module. Thus, this kind of nesting should be avoided when possible. +The `unstable` attribute may also have the `soft` value, which makes it a +future-incompatible deny-by-default lint instead of a hard error. This is used +by the `bench` attribute which was accidentally accepted in the past. This +prevents breaking dependencies by leveraging Cargo's lint capping. + [rustc bug]: https://github.com/rust-lang/rust/issues/15702 -# stable +## stable The `#[stable(feature = "foo", "since = "1.420.69")]` attribute explicitly marks an item as stabilized. To do this, follow the instructions in @@ -31,7 +41,7 @@ stabilized. To do this, follow the instructions in Note that stable functions may use unstable things in their body. -# allow_internal_unstable +## allow_internal_unstable Macros, compiler desugarings and `const fn`s expose their bodies to the call site. To work around not being able to use unstable things in the standard library's macros, there's the @@ -49,4 +59,71 @@ are nondeterministic and often unknown at compile-time. Always ping @oli-obk, @RalfJung, and @Centril if you are adding more `allow_internal_unstable` attributes to any `const fn` +## staged_api + +Any crate that uses the `stable`, `unstable`, or `rustc_deprecated` attributes +must include the `#![feature(staged_api)]` attribute on the crate. + +## rustc_deprecated + +The deprecation system shares the same infrastructure as the stable/unstable +attributes. The `rustc_deprecated` attribute is similar to the [`deprecated` +attribute]. It was previously called `deprecated`, but was split off when +`deprecated` was stabilized. The `deprecated` attribute cannot be used in a +`staged_api` crate, `rustc_deprecated` must be used instead. The deprecated +item must also have a `stable` or `unstable` attribute. + +`rustc_deprecated` has the following form: + +```rust,ignore +#[rustc_deprecated( + since = "1.38.0", + reason = "explanation for deprecation", + suggestion = "other_function" +)] +``` + +The `suggestion` field is optional. If given, it should be a string that can +be used as a machine-applicable suggestion to correct the warning. This is +typically used when the identifier is renamed, but no other significant +changes are necessary. + +Another difference from the `deprecated` attribute is that the `since` field +is actually checked against the current version of `rustc`. If `since` is in a +future version, then the `deprecated_in_future` lint is triggered which is +default `allow`, but most of the standard library raises it to a warning with +`#![warn(deprecated_in_future)]`. + +[`deprecated` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute + +## -Zforce-unstable-if-unmarked + +The `-Zforce-unstable-if-unmarked` flag has a variety of purposes to help +enforce that the correct crates are marked as unstable. It was introduced +primarily to allow rustc and the standard library to link to arbitrary crates +on crates.io which do not themselves use `staged_api`. `rustc` also relies on +this flag to mark all of its crates as unstable with the `rustc_private` +feature so that each crate does not need to be carefully marked with +`unstable`. + +This flag is automatically applied to all of `rustc` and the standard library +by the bootstrap scripts. This is needed because the compiler and all of its +dependencies are shipped in the sysroot to all users. + +This flag has the following effects: + +- Marks the crate as "unstable" with the `rustc_private` feature if it is not + itself marked as stable or unstable. +- Allows these crates to access other forced-unstable crates without any need + for attributes. Normally a crate would need a `#![feature(rustc_private)]` + attribute to use other unstable crates. However, that would make it + impossible for a crate from crates.io to access its own dependencies since + that crate won't have a `feature(rustc_private)` attribute, but *everything* + is compiled with `-Zforce-unstable-if-unmarked`. + +Code which does not use `-Zforce-unstable-if-unmarked` should include the +`#![feature(rustc_private)]` crate attribute to access these force-unstable +crates. This is needed for things that link `rustc`, such as `miri`, `rls`, or +`clippy`. + [blog]: https://www.ralfj.de/blog/2018/07/19/const.html diff --git a/src/doc/rustc-guide/src/test-implementation.md b/src/doc/rustc-guide/src/test-implementation.md index 969d6d2e49..59cc7c5bdd 100644 --- a/src/doc/rustc-guide/src/test-implementation.md +++ b/src/doc/rustc-guide/src/test-implementation.md @@ -25,7 +25,7 @@ mod my_priv_mod { } ``` Private items can thus be easily tested without worrying about how to expose -the them to any sort of external testing apparatus. This is key to the +them to any sort of external testing apparatus. This is key to the ergonomics of testing in Rust. Semantically, however, it's rather odd. How does any sort of `main` function invoke these tests if they're not visible? What exactly is `rustc --test` doing? diff --git a/src/doc/rustc-guide/src/tests/adding.md b/src/doc/rustc-guide/src/tests/adding.md index a660d26b56..8492cbbcc9 100644 --- a/src/doc/rustc-guide/src/tests/adding.md +++ b/src/doc/rustc-guide/src/tests/adding.md @@ -49,12 +49,13 @@ considered an ideal setup. [`src/test/ui`]: https://github.com/rust-lang/rust/tree/master/src/test/ui/ For regression tests – basically, some random snippet of code that -came in from the internet – we often just name the test after the -issue. For example, `src/test/ui/issue-12345.rs`. If possible, -though, it is better if you can put the test into a directory that -helps identify what piece of code is being tested here (e.g., -`borrowck/issue-12345.rs` is much better), or perhaps give it a more -meaningful name. Still, **do include the issue number somewhere**. +came in from the internet – we often name the test after the issue +plus a short description. Ideally, the test should be added to a +directory that helps identify what piece of code is being tested here +(e.g., `src/test/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs`) +If you've tried and cannot find a more relevant place, +the test may be added to `src/test/ui/issues/`. +Still, **do include the issue number somewhere**. When writing a new feature, **create a subdirectory to store your tests**. For example, if you are implementing RFC 1234 ("Widgets"), diff --git a/src/doc/rustc-guide/src/tests/intro.md b/src/doc/rustc-guide/src/tests/intro.md index c043da4296..4572d23ca9 100644 --- a/src/doc/rustc-guide/src/tests/intro.md +++ b/src/doc/rustc-guide/src/tests/intro.md @@ -5,7 +5,7 @@ by the build system (`x.py test`). The main test harness for testing the compiler itself is a tool called compiletest (sources in the [`src/tools/compiletest`]). This section gives a brief overview of how the testing framework is setup, and then gets into some of the details -on [how to run tests](./running.html#ui) as well as +on [how to run tests](./running.html) as well as [how to add new tests](./adding.html). [`src/tools/compiletest`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest @@ -26,9 +26,7 @@ that give more details. - [`ui`](./adding.html#ui) – tests that check the exact stdout/stderr from compilation and/or running the test -- `run-pass` – tests that are expected to compile and execute - successfully (no panics) - - `run-pass-valgrind` – tests that ought to run with valgrind +- `run-pass-valgrind` – tests that ought to run with valgrind - `run-fail` – tests that are expected to compile but then panic during execution - `compile-fail` – tests that are expected to fail compilation. @@ -103,27 +101,27 @@ including: ## Testing infrastructure -When a Pull Request is opened on Github, [Travis] will automatically launch a -build that will run all tests on a single configuration (x86-64 linux). In -essence, it runs `./x.py test` after building. +When a Pull Request is opened on Github, [Azure Pipelines] will automatically +launch a build that will run all tests on some configurations +(x86_64-gnu-llvm-6.0 linux. x86_64-gnu-tools linux, mingw-check linux). In +essence, it runs `./x.py test` after building for each of them. The integration bot [bors] is used for coordinating merges to the master branch. When a PR is approved, it goes into a [queue] where merges are tested -one at a time on a wide set of platforms using Travis and [Appveyor] -(currently over 50 different configurations). Most platforms only run the -build steps, some run a restricted set of tests, only a subset run the full -suite of tests (see Rust's [platform tiers]). +one at a time on a wide set of platforms using Azure Pipelines (currently over +50 different configurations). Most platforms only run the build steps, some run +a restricted set of tests, only a subset run the full suite of tests (see +Rust's [platform tiers]). -[Travis]: https://travis-ci.org/rust-lang/rust +[Azure Pipelines]: https://dev.azure.com/rust-lang/rust/ [bors]: https://github.com/servo/homu [queue]: https://buildbot2.rust-lang.org/homu/queue/rust -[Appveyor]: https://ci.appveyor.com/project/rust-lang/rust [platform tiers]: https://forge.rust-lang.org/platform-support.html ## Testing with Docker images The Rust tree includes [Docker] image definitions for the platforms used on -Travis in [src/ci/docker]. The script [src/ci/docker/run.sh] is used to build +Azure Pipelines in [src/ci/docker]. The script [src/ci/docker/run.sh] is used to build the Docker image, run it, build Rust within the image, and run the tests. > TODO: What is a typical workflow for testing/debugging on a platform that diff --git a/src/doc/rustc-guide/src/tests/running.md b/src/doc/rustc-guide/src/tests/running.md index ef3227f9ab..4a86d2cce8 100644 --- a/src/doc/rustc-guide/src/tests/running.md +++ b/src/doc/rustc-guide/src/tests/running.md @@ -4,7 +4,7 @@ You can run the tests using `x.py`. The most basic command – which you will almost never want to use! – is as follows: ```bash -> ./x.py test +./x.py test ``` This will build the full stage 2 compiler and then run the whole test @@ -34,7 +34,7 @@ test" that can be used after modifying rustc to see if things are generally working correctly would be the following: ```bash -> ./x.py test --stage 1 src/test/{ui,compile-fail} +./x.py test --stage 1 src/test/{ui,compile-fail} ``` This will run the `ui` and `compile-fail` test suites, @@ -44,38 +44,38 @@ example, if you are hacking on debuginfo, you may be better off with the debuginfo test suite: ```bash -> ./x.py test --stage 1 src/test/debuginfo +./x.py test --stage 1 src/test/debuginfo ``` If you only need to test a specific subdirectory of tests for any given test suite, you can pass that directory to `x.py test`: ```bash -> ./x.py test --stage 1 src/test/ui/const-generics +./x.py test --stage 1 src/test/ui/const-generics ``` Likewise, you can test a single file by passing its path: ```bash -> ./x.py test --stage 1 src/test/ui/const-generics/const-test.rs +./x.py test --stage 1 src/test/ui/const-generics/const-test.rs ``` ### Run only the tidy script ```bash -> ./x.py test src/tools/tidy +./x.py test src/tools/tidy ``` ### Run tests on the standard library ```bash -> ./x.py test src/libstd +./x.py test src/libstd ``` ### Run tests on the standard library and run the tidy script ```bash -> ./x.py test src/libstd src/tools/tidy +./x.py test src/libstd src/tools/tidy ``` ### Run tests on the standard library using a stage 1 compiler @@ -100,7 +100,7 @@ you may pass the full file path to achieve this, or alternatively one may invoke `x.py` with the `--test-args` option: ```bash -> ./x.py test --stage 1 src/test/ui --test-args issue-1234 +./x.py test --stage 1 src/test/ui --test-args issue-1234 ``` Under the hood, the test runner invokes the standard rust test runner @@ -117,13 +117,13 @@ exists in the test file. For example, you can run all the tests in `src/test/ui` as `check-pass`: ```bash -> ./x.py test --stage 1 src/test/ui --pass check +./x.py test --stage 1 src/test/ui --pass check ``` By passing `--pass $mode`, you can reduce the testing time. For each mode, please see [here][mode]. -[mode]: https://rust-lang.github.io/rustc-guide/tests/adding.html#tests-that-do-not-result-in-compile-errors +[mode]: ./adding.md#tests-that-do-not-result-in-compile-errors ## Using incremental compilation @@ -131,7 +131,7 @@ You can further enable the `--incremental` flag to save additional time in subsequent rebuilds: ```bash -> ./x.py test --stage 1 src/test/ui --incremental --test-args issue-1234 +./x.py test --stage 1 src/test/ui --incremental --test-args issue-1234 ``` If you don't want to include the flag with every command, you can @@ -152,7 +152,7 @@ Sometimes it's easier and faster to just run the test by hand. Most tests are just `rs` files, so you can do something like ```bash -> rustc +stage1 src/test/ui/issue-1234.rs +rustc +stage1 src/test/ui/issue-1234.rs ``` This is much faster, but doesn't always work. For example, some tests diff --git a/src/doc/rustc-guide/src/the-parser.md b/src/doc/rustc-guide/src/the-parser.md index 5796ae40ec..d089a84181 100644 --- a/src/doc/rustc-guide/src/the-parser.md +++ b/src/doc/rustc-guide/src/the-parser.md @@ -1,29 +1,35 @@ -# The Parser +# Lexing and Parsing -The parser is responsible for converting raw Rust source code into a structured -form which is easier for the compiler to work with, usually called an [*Abstract -Syntax Tree*][ast]. An AST mirrors the structure of a Rust program in memory, -using a `Span` to link a particular AST node back to its source text. +> The parser and lexer are currently undergoing a lot of refactoring, so parts +> of this chapter may be out of date. + +The very first thing the compiler does is take the program (in Unicode +characters) and turn it into something the compiler can work with more +conveniently than strings. This happens in two stages: Lexing and Parsing. -The bulk of the parser lives in the [libsyntax] crate. +Lexing takes strings and turns them into streams of tokens. For example, +`a.b + c` would be turned into the tokens `a`, `.`, `b`, `+`, and `c`. +The lexer lives in [`librustc_lexer`][lexer]. -Like most parsers, the parsing process is composed of two main steps, +[lexer]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lexer/index.html -- lexical analysis – turn a stream of characters into a stream of token trees -- parsing – turn the token trees into an AST +Parsing then takes streams of tokens and turns them into a structured +form which is easier for the compiler to work with, usually called an [*Abstract +Syntax Tree*][ast] (AST). An AST mirrors the structure of a Rust program in memory, +using a `Span` to link a particular AST node back to its source text. -The `syntax` crate contains several main players, +The AST is defined in [`libsyntax`][libsyntax], along with some definitions for +tokens and token streams, data structures/traits for mutating ASTs, and shared +definitions for other AST-related parts of the compiler (like the lexer and +macro-expansion). -- a [`SourceMap`] for mapping AST nodes to their source code -- the [ast module] contains types corresponding to each AST node -- a [`StringReader`] for lexing source code into tokens -- the [parser module] and [`Parser`] struct are in charge of actually parsing - tokens into AST nodes, -- and a [visit module] for walking the AST and inspecting or mutating the AST - nodes. +The parser is defined in [`librustc_parse`][librustc_parse], along with a +high-level interface to the lexer and some validation routines that run after +macro expansion. In particular, the [`rustc_parser::parser`][parser] contains +the parser implementation. The main entrypoint to the parser is via the various `parse_*` functions in the -[parser module]. They let you do things like turn a [`SourceFile`][sourcefile] +[parser][parser]. They let you do things like turn a [`SourceFile`][sourcefile] (e.g. the source in a single file) into a token stream, create a parser from the token stream, and then execute the parser to get a `Crate` (the root AST node). @@ -44,14 +50,14 @@ Code for lexical analysis is split between two crates: specific data structures. Specifically, it adds `Span` information to tokens returned by `rustc_lexer` and interns identifiers. - [libsyntax]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/index.html [rustc_errors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html [ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html [ast module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/index.html -[parser module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/index.html +[librustc_parse]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html +[parser]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/index.html [`Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/parser/struct.Parser.html -[`StringReader`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/lexer/struct.StringReader.html +[`StringReader`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.StringReader.html [visit module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/visit/index.html [sourcefile]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceFile.html diff --git a/src/doc/rustc-guide/src/traits/chalk-overview.md b/src/doc/rustc-guide/src/traits/chalk-overview.md index 0a95585f6d..0f102d4d04 100644 --- a/src/doc/rustc-guide/src/traits/chalk-overview.md +++ b/src/doc/rustc-guide/src/traits/chalk-overview.md @@ -211,7 +211,7 @@ Likewise, lowering tests use the [`lowering_success!` and * [Lowering Rust traits to logic](http://smallcultfollowing.com/babysteps/blog/2017/01/26/lowering-rust-traits-to-logic/) * [Unification in Chalk, part 1](http://smallcultfollowing.com/babysteps/blog/2017/03/25/unification-in-chalk-part-1/) * [Unification in Chalk, part 2](http://smallcultfollowing.com/babysteps/blog/2017/04/23/unification-in-chalk-part-2/) -* [Negative reasoning in Chalk](http://aturon.github.io/blog/2017/04/24/negative-chalk/) +* [Negative reasoning in Chalk](https://aturon.github.io/blog/2017/04/24/negative-chalk/) * [Query structure in chalk](http://smallcultfollowing.com/babysteps/blog/2017/05/25/query-structure-in-chalk/) * [Cyclic queries in chalk](http://smallcultfollowing.com/babysteps/blog/2017/09/12/tabling-handling-cyclic-queries-in-chalk/) * [An on-demand SLG solver for chalk](http://smallcultfollowing.com/babysteps/blog/2018/01/31/an-on-demand-slg-solver-for-chalk/) @@ -229,28 +229,28 @@ Likewise, lowering tests use the [`lowering_success!` and [rustc-issues]: https://github.com/rust-lang/rustc-guide/issues [universal quantification]: https://en.wikipedia.org/wiki/Universal_quantification -[`ProgramClause`]: https://rust-lang.github.io/chalk/doc/chalk_ir/enum.ProgramClause.html -[`ProgramEnvironment`]: http://rust-lang.github.io/chalk/doc/chalk/program_environment/struct.ProgramEnvironment.html -[chalk_engine]: https://rust-lang.github.io/chalk/doc/chalk_engine/index.html -[chalk_ir]: https://rust-lang.github.io/chalk/doc/chalk_ir/index.html -[chalk_parse]: https://rust-lang.github.io/chalk/doc/chalk_parse/index.html -[chalk_solve]: https://rust-lang.github.io/chalk/doc/chalk_solve/index.html -[chalk_rust_ir]: https://rust-lang.github.io/chalk/doc/chalk_rust_ir/index.html -[doc-chalk]: https://rust-lang.github.io/chalk/doc/chalk/index.html -[engine-context]: https://rust-lang.github.io/chalk/doc/chalk_engine/context/index.html -[chalk-program]: http://rust-lang.github.io/chalk/doc/chalk/program/struct.Program.html - -[binders-struct]: http://rust-lang.github.io/chalk/doc/chalk_ir/struct.Binders.html -[chalk-ast]: http://rust-lang.github.io/chalk/doc/chalk_parse/ast/index.html +[`ProgramClause`]: https://rust-lang.github.io/chalk/chalk_ir/enum.ProgramClause.html +[`ProgramEnvironment`]: https://rust-lang.github.io/chalk/chalk_integration/program_environment/struct.ProgramEnvironment.html +[chalk_engine]: https://rust-lang.github.io/chalk/chalk_engine +[chalk_ir]: https://rust-lang.github.io/chalk/chalk_ir/index.html +[chalk_parse]: https://rust-lang.github.io/chalk/chalk_parse/index.html +[chalk_solve]: https://rust-lang.github.io/chalk/chalk_solve/index.html +[chalk_rust_ir]: https://rust-lang.github.io/chalk/chalk_rust_ir/index.html +[doc-chalk]: https://rust-lang.github.io/chalk/chalk/index.html +[engine-context]: https://rust-lang.github.io/chalk/chalk_engine/context/index.html +[chalk-program]: https://rust-lang.github.io/chalk/chalk_integration/program/struct.Program.html + +[binders-struct]: https://rust-lang.github.io/chalk/chalk_ir/struct.Binders.html +[chalk-ast]: https://rust-lang.github.io/chalk/chalk_parse/ast/index.html [chalk-test-example]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L115 [chalk-test-lowering-example]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/rust_ir/lowering/test.rs#L8-L31 [chalk-test-lowering]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/rust_ir/lowering/test.rs [chalk-test-wf]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/rules/wf/test.rs#L1 -[chalki]: https://rust-lang.github.io/chalk/doc/chalki/index.html +[chalki]: https://github.com/rust-lang/chalk/blob/master/src/main.rs [clause]: https://github.com/rust-lang/chalk/blob/master/GLOSSARY.md#clause -[coherence-src]: http://rust-lang.github.io/chalk/doc/chalk_solve/coherence/index.html -[ir-code]: http://rust-lang.github.io/chalk/doc/chalk_rust_ir/ -[solve-wf-src]: http://rust-lang.github.io/chalk/doc/chalk_solve/wf/index.html +[coherence-src]: https://rust-lang.github.io/chalk/chalk_solve/coherence/index.html +[ir-code]: https://rust-lang.github.io/chalk/chalk_rust_ir/ +[solve-wf-src]: https://rust-lang.github.io/chalk/chalk_solve/wf/index.html [solve_goal]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L85 [test-lowering-macros]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test_util.rs#L21-L54 [test-macro]: https://github.com/rust-lang/chalk/blob/4bce000801de31bf45c02f742a5fce335c9f035f/src/test.rs#L33 diff --git a/src/doc/rustc-guide/src/traits/slg.md b/src/doc/rustc-guide/src/traits/slg.md index 948d3fc8ab..74ec89fa02 100644 --- a/src/doc/rustc-guide/src/traits/slg.md +++ b/src/doc/rustc-guide/src/traits/slg.md @@ -47,7 +47,7 @@ well as the various *strands*, which are basically suspended computations that may be used to find more answers. Tables are interdependent: solving one query may require solving others. -[`Forest`]: https://rust-lang.github.io/chalk/doc/chalk_engine/forest/struct.Forest.html +[`Forest`]: https://rust-lang.github.io/chalk/chalk_engine/forest/struct.Forest.html ### Walkthrough @@ -126,7 +126,7 @@ literals and region constraints, an X-clause just looks like this: ```text G :- L ``` - + where G is a goal and L is a set of subgoals that must be proven. (The L stands for *literal* -- when we address negative reasoning, a literal will be either a positive or negative subgoal.) The idea is @@ -150,7 +150,7 @@ is the subgoal after the turnstile (`:-`) that we are currently trying to prove in this strand. Initially, when a strand is first created, there is no selected subgoal. -[`ExClause`]: https://rust-lang.github.io/chalk/doc/chalk_engine/struct.ExClause.html +[`ExClause`]: https://rust-lang.github.io/chalk/chalk_engine/struct.ExClause.html **Activating a strand.** Now that we have created the table T0 and initialized it with strands, we have to actually try and produce an answer. @@ -182,12 +182,12 @@ the state of the strand to: ```text (Rc: Debug) :- selected(?T: Debug, A0) ``` - + Here, we write `selected(L, An)` to indicate that (a) the literal `L` is the selected subgoal and (b) which answer `An` we are looking for. We start out looking for `A0`. -[`ensure_root_answer`]: https://rust-lang.github.io/chalk/doc/chalk_engine/forest/struct.Forest.html#method.ensure_root_answer +[`ensure_root_answer`]: https://rust-lang.github.io/chalk/chalk_engine/forest/struct.Forest.html#method.ensure_root_answer **Processing the selected subgoal.** Next, we have to try and find an answer to this selected goal. To do that, we will u-canonicalize it @@ -210,14 +210,14 @@ follows: Table T0 [Rc: Debug] Strands: (Rc: Debug) :- selected(?T: Debug, A0) - + Table T1 [?0: Debug] Strands: (u32: Debug) :- (Vec: Debug) :- (?U: Debug) (Rc: Debug) :- (?V: Debug) ``` - + **Delegation between tables.** Now that the active strand from T0 has created the table T1, it can try to extract an answer. It does this via that same `ensure_answer` operation we saw before. In this case, @@ -299,4 +299,4 @@ more answers later on. [readme]: https://github.com/rust-lang/chalk/blob/239e4ae4e69b2785b5f99e0f2b41fc16b0b4e65e/chalk-engine/src/README.md [slg-blog]: http://smallcultfollowing.com/babysteps/blog/2018/01/31/an-on-demand-slg-solver-for-chalk/ -[negative-reasoning-blog]: http://aturon.github.io/blog/2017/04/24/negative-chalk/ +[negative-reasoning-blog]: https://aturon.github.io/blog/2017/04/24/negative-chalk/ diff --git a/src/doc/rustc-guide/src/traits/wf.md b/src/doc/rustc-guide/src/traits/wf.md index 0ced345a15..aa17f8c2c6 100644 --- a/src/doc/rustc-guide/src/traits/wf.md +++ b/src/doc/rustc-guide/src/traits/wf.md @@ -13,12 +13,12 @@ say that the construct is well-formed. If not, we report an error to the user. Well-formedness checking happens in the [`chalk/chalk-solve/src/wf.rs`][wf] module in chalk. After you have read this chapter, you may find useful to see -an extended set of examples in the [`chalk/src/test/wf.rs`][wf_test] submodule. +an extended set of examples in the [`chalk/tests/test/wf_lowering.rs`][wf_test] submodule. The new-style WF checking has not been implemented in rustc yet. [wf]: https://github.com/rust-lang/chalk/blob/master/chalk-solve/src/wf.rs -[wf_test]: https://github.com/rust-lang/chalk/blob/master/src/test/wf.rs +[wf_test]: https://github.com/rust-lang/chalk/blob/master/tests/test/wf_lowering.rs We give here a complete reference of the generated goals for each Rust declaration. diff --git a/src/doc/rustc-guide/src/ty.md b/src/doc/rustc-guide/src/ty.md index 811f473c9b..6295a0db1d 100644 --- a/src/doc/rustc-guide/src/ty.md +++ b/src/doc/rustc-guide/src/ty.md @@ -60,8 +60,8 @@ defining all of the different kinds of types in the compiler. > N.B. inspecting the `sty` field on types during type inference can be > risky, as there may be inference variables and other things to -> consider, or sometimes types are not yet known that will become -> known later.). +> consider, or sometimes types are not yet known and will become +> known later. To allocate a new type, you can use the various `mk_` methods defined on the `tcx`. These have names that correspond mostly to the various kinds @@ -109,7 +109,7 @@ module. Here are a few examples: - `Predicate` defines something the trait system has to prove (see `traits` module). -[subst]: ./kinds.html#subst +[subst]: ./generic_arguments.html#subst ### Import conventions diff --git a/src/doc/rustc-guide/src/variance.md b/src/doc/rustc-guide/src/variance.md index c6a1a320bb..af23330e8a 100644 --- a/src/doc/rustc-guide/src/variance.md +++ b/src/doc/rustc-guide/src/variance.md @@ -99,7 +99,7 @@ parameter `X` with respect to its defining class. `Term x Term` represents the "variance transform" as defined in the paper: > If the variance of a type variable `X` in type expression `E` is `V2` - and the definition-site variance of the [corresponding] type parameter + and the definition-site variance of the corresponding type parameter of a class `C` is `V1`, then the variance of `X` in the type expression `C` is `V3 = V1.xform(V2)`. diff --git a/src/doc/rustc-guide/src/walkthrough.md b/src/doc/rustc-guide/src/walkthrough.md index e2e96fced9..5d54404efa 100644 --- a/src/doc/rustc-guide/src/walkthrough.md +++ b/src/doc/rustc-guide/src/walkthrough.md @@ -47,7 +47,7 @@ before, not all of these are needed for every type of contribution. audience. You can find the original discussion [here][prerfc]. - **RFC** This is when you formally present your idea to the community for consideration. You can find the RFC [here][rfc]. -- **Implementation** Implement your idea unstabley in the compiler. You can +- **Implementation** Implement your idea unstably in the compiler. You can find the original implementation [here][impl1]. - **Possibly iterate/refine** As the community gets experience with your feature on the nightly compiler and in `libstd`, there may be additional @@ -120,13 +120,13 @@ itself to reflect the course of the discussion (e.g. new alternatives or prior work may be added or you may decide to change parts of the proposal itself). In the end, when the discussion seems to reach a consensus and die down a bit, -a rust team member may propose to move to FCP with one of three possible dispositions. -This means that they want the other members of the appropriate teams to review -and comment on the RFC. More discussion may ensue, which may result in more changes -or unresolved questions being added. At some point, when everyone is -satisfied, the RFC enters the "final comment period" (FCP), which is the last -chance for people to bring up objections. When the FCP is over, the disposition is -adopted. Here are the three possible dispositions: +a rust team member may propose to move to "final comment period" (FCP) with one +of three possible dispositions. This means that they want the other members of +the appropriate teams to review and comment on the RFC. More discussion may +ensue, which may result in more changes or unresolved questions being added. At +some point, when everyone is satisfied, the RFC enters the FCP, which is the +last chance for people to bring up objections. When the FCP is over, the +disposition is adopted. Here are the three possible dispositions: - _Merge_: accept the feature. Here is the proposal to merge for our [`?` macro feature][rfcmerge]. diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index f5d5f2089d..0dc81378e0 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -9,9 +9,12 @@ This option is deprecated and does nothing. ## linker -This flag lets you control which linker `rustc` invokes to link your code. +This flag lets you control which linker `rustc` invokes to link your code. It +takes a path to the linker executable. If this flag is not specified, the +linker will be inferred based on the target. See also the +[linker-flavor](#linker-flavor) flag for another way to specify the linker. -## link-arg=val +## link-arg This flag lets you append a single extra argument to the linker invocation. @@ -25,9 +28,27 @@ options should be separated by spaces. ## linker-flavor This flag lets you control the linker flavor used by `rustc`. If a linker is given with the -`-C linker` flag described above then the linker flavor is inferred from the value provided. If no +[`-C linker` flag](#linker), then the linker flavor is inferred from the value provided. If no linker is given then the linker flavor is used to determine the linker to use. Every `rustc` target -defaults to some linker flavor. +defaults to some linker flavor. Valid options are: + +* `em`: Uses [Emscripten `emcc`](https://emscripten.org/docs/tools_reference/emcc.html). +* `gcc`: Uses the `cc` executable, which is typically gcc or clang on many systems. +* `ld`: Uses the `ld` executable. +* `msvc`: Uses the `link.exe` executable from Microsoft Visual Studio MSVC. +* `ptx-linker`: Uses + [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) for Nvidia + NVPTX GPGPU support. +* `wasm-ld`: Uses the [`wasm-ld`](https://lld.llvm.org/WebAssembly.html) + executable, a port of LLVM `lld` for WebAssembly. +* `ld64.lld`: Uses the LLVM `lld` executable with the [`-flavor darwin` + flag][lld-flavor] for Apple's `ld`. +* `ld.lld`: Uses the LLVM `lld` executable with the [`-flavor gnu` + flag][lld-flavor] for GNU binutils' `ld`. +* `lld-link`: Uses the LLVM `lld` executable with the [`-flavor link` + flag][lld-flavor] for Microsoft's `link.exe`. + +[lld-flavor]: https://lld.llvm.org/Driver.html ## link-dead-code @@ -39,11 +60,44 @@ metrics. ## lto This flag instructs LLVM to use [link time -optimizations](https://llvm.org/docs/LinkTimeOptimization.html). +optimizations](https://llvm.org/docs/LinkTimeOptimization.html) to produce +better optimized code, using whole-program analysis, at the cost of longer +linking time. -It takes one of two values, `thin` and `fat`. 'thin' LTO [is a new feature of -LLVM](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html), -'fat' referring to the classic version of LTO. +This flag may take one of the following values: + +* `y`, `yes`, `on`, `fat`, or no value: Performs "fat" LTO which attempts to + perform optimizations across all crates within the dependency graph. +* `n`, `no`, `off`: Disables LTO. +* `thin`: Performs ["thin" + LTO](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html). + This is similar to "fat", but takes substantially less time to run while + still achieving performance gains similar to "fat". + +If `-C lto` is not specified, then the compiler will attempt to perform "thin +local LTO" which performs "thin" LTO on the local crate only across its +[codegen units](#codegen-units). When `-C lto` is not specified, LTO is +disabled if codegen units is 1 or optimizations are disabled ([`-C +opt-level=0`](#opt-level)). That is: + +* When `-C lto` is not specified: + * `codegen-units=1`: Disables LTO. + * `opt-level=0`: Disables LTO. +* When `-C lto=true`: + * `lto=true`: 16 codegen units, performs fat LTO across crates. + * `codegen-units=1` + `lto=true`: 1 codegen unit, fat LTO across crates. + +See also [linker-plugin-lto](#linker-plugin-lto) for cross-language LTO. + +## linker-plugin-lto + +Defers LTO optimizations to the linker. See +[linkger-plugin-LTO](../linker-plugin-lto.md) for more details. Takes one of +the following values: + +* `y`, `yes`, `on`, or no value: Enabled. +* `n`, `no`, or `off`: Disabled (default). +* A path to the linker plugin. ## target-cpu @@ -51,30 +105,47 @@ This instructs `rustc` to generate code specifically for a particular processor. You can run `rustc --print target-cpus` to see the valid options to pass here. Additionally, `native` can be passed to use the processor of the host -machine. +machine. Each target has a default base CPU. ## target-feature Individual targets will support different features; this flag lets you control -enabling or disabling a feature. +enabling or disabling a feature. Each feature should be prefixed with a `+` to +enable it or `-` to disable it. Separate multiple features with commas. To see the valid options and an example of use, run `rustc --print target-features`. -Using this flag is unsafe and might result in [undefined runtime behavior](../targets/known-issues.md). +Using this flag is unsafe and might result in [undefined runtime +behavior](../targets/known-issues.md). + +See also the [`target_feature` +attribute](../../reference/attributes/codegen.md#the-target_feature-attribute) +for controlling features per-function. + +This also supports the feature `+crt-static` and `-crt-static` to control +[static C runtime linkage](../../reference/linkage.html#static-and-dynamic-c-runtimes). + +Each target and [`target-cpu`](#target-cpu) has a default set of enabled +features. ## passes -This flag can be used to add extra LLVM passes to the compilation. +This flag can be used to add extra [LLVM +passes](http://llvm.org/docs/Passes.html) to the compilation. The list must be separated by spaces. +See also the [`no-prepopulate-passes`](#no-prepopulate-passes) flag. + ## llvm-args This flag can be used to pass a list of arguments directly to LLVM. The list must be separated by spaces. +Pass `--help` to see a list of options. + ## save-temps `rustc` will generate temporary files during compilation; normally it will @@ -83,16 +154,21 @@ preserved instead of removed. ## rpath -This option allows you to set the value of +This option allows you to enable [`rpath`](https://en.wikipedia.org/wiki/Rpath). ## overflow-checks -This flag allows you to control the behavior of integer overflow. This flag -can be passed many options: +This flag allows you to control the behavior of [runtime integer +overflow](../../reference/expressions/operator-expr.md#overflow). When +overflow-checks are enabled, a panic will occur on overflow. This flag takes +one of the following values: -* To turn overflow checks on: `y`, `yes`, or `on`. -* To turn overflow checks off: `n`, `no`, or `off`. +* `y`, `yes`, `on`, or no value: Enable overflow checks. +* `n`, `no`, or `off`: Disable overflow checks. + +If not specified, overflow checks are enabled if +[debug-assertions](#debug-assertions) are enabled, disabled otherwise. ## no-prepopulate-passes @@ -121,29 +197,38 @@ in software. ## prefer-dynamic By default, `rustc` prefers to statically link dependencies. This option will -make it use dynamic linking instead. +indicate that dynamic linking should be used if possible if both a static and +dynamic versions of a library are available. There is an internal algorithm +for determining whether or not it is possible to statically or dynamically +link with a dependency. For example, `cdylib` crate types may only use static +linkage. ## no-integrated-as -LLVM comes with an internal assembler; this option will let you use an -external assembler instead. +`rustc` normally uses the LLVM internal assembler to create object code. This +flag will disable the internal assembler and emit assembly code to be +translated using an external assembler, currently the linker such as `cc`. ## no-redzone This flag allows you to disable [the red zone](https://en.wikipedia.org/wiki/Red_zone_\(computing\)). This flag can -be passed many options: +be passed one of the following options: + +* `y`, `yes`, `on`, or no value: Disables the red zone. +* `n`, `no`, or `off`: Enables the red zone. -* To enable the red zone: `y`, `yes`, or `on`. -* To disable it: `n`, `no`, or `off`. +The default if not specified depends on the target. ## relocation-model -This option lets you choose which relocation model to use. +This option lets you choose which +[relocation](https://en.wikipedia.org/wiki/Relocation_\(computing\)) model to +use. To find the valid options for this flag, run `rustc --print relocation-models`. -## code-model=val +## code-model This option lets you choose which code model to use. @@ -151,23 +236,34 @@ To find the valid options for this flag, run `rustc --print code-models`. ## metadata -This option allows you to control the metadata used for symbol mangling. +This option allows you to control the metadata used for symbol mangling. This +takes a space-separated list of strings. Mangled symbols will incorporate a +hash of the metadata. This may be used, for example, to differentiate symbols +between two different versions of the same crate being linked. ## extra-filename -This option allows you to put extra data in each output filename. +This option allows you to put extra data in each output filename. It takes a +string to add as a suffix to the filename. See the [`--emit` +flag][option-emit] for more information. ## codegen-units -This flag lets you control how many threads are used when doing -code generation. +This flag controls how many code generation units the crate is split into. It +takes an integer greater than 0. -Increasing parallelism may speed up compile times, but may also -produce slower code. +When a crate is split into multiple codegen units, LLVM is able to process +them in parallel. Increasing parallelism may speed up compile times, but may +also produce slower code. Setting this to 1 may improve the performance of +generated code, but may be slower to compile. + +The default, if not specified, is 16. This flag is ignored if +[incremental](#incremental) is enabled, in which case an internal heuristic is +used to split the crate. ## remark -This flag lets you print remarks for these optimization passes. +This flag lets you print remarks for optimization passes. The list of passes should be separated by spaces. @@ -181,30 +277,55 @@ This option is deprecated and does nothing. This flag lets you control debug information: -* `0`: no debug info at all +* `0`: no debug info at all (default) * `1`: line tables only * `2`: full debug info +Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`. + ## opt-level This flag lets you control the optimization level. -* `0`: no optimizations, also turn on `cfg(debug_assertions)`. +* `0`: no optimizations, also turns on [`cfg(debug_assertions)`](#debug-assertions). * `1`: basic optimizations * `2`: some optimizations * `3`: all optimizations * `s`: optimize for binary size * `z`: optimize for binary size, but also turn off loop vectorization. +Note: The [`-O` flag][option-o-optimize] is an alias for `-C opt-level=2`. + +The default is `0`. + ## debug-assertions -This flag lets you turn `cfg(debug_assertions)` on or off. +This flag lets you turn `cfg(debug_assertions)` [conditional +compilation](../../reference/conditional-compilation.md#debug_assertions) on +or off. It takes one of the following values: + +* `y`, `yes`, `on`, or no value: Enable debug-assertions. +* `n`, `no`, or `off`: Disable debug-assertions. + +If not specified, debug assertions are automatically enabled only if the +[opt-level](#opt-level) is 0. ## inline-threshold -This option lets you set the threshold for inlining a function. +This option lets you set the default threshold for inlining a function. It +takes an unsigned integer as a value. Inlining is based on a cost model, where +a higher threshold will allow more inlining. -The default is 225. +The default depends on the [opt-level](#opt-level): + +| opt-level | Threshold | +|-----------|-----------| +| 0 | N/A, only inlines always-inline functions | +| 1 | N/A, only inlines always-inline functions and LLVM lifetime intrinsics | +| 2 | 225 | +| 3 | 275 | +| s | 75 | +| z | 25 | ## panic @@ -213,9 +334,14 @@ This option lets you control what happens when the code panics. * `abort`: terminate the process upon panic * `unwind`: unwind the stack upon panic +If not specified, the default depends on the target. + ## incremental -This flag allows you to enable incremental compilation. +This flag allows you to enable incremental compilation, which allows `rustc` +to save information after compiling a crate to be reused when recompiling the +crate, improving re-compile times. This takes a path to a directory where +incremental files will be stored. ## profile-generate @@ -232,4 +358,31 @@ optimization (PGO). The flag takes a mandatory argument which is the path to a valid `.profdata` file. See the chapter on [profile-guided optimization] for more information. +## force-frame-pointers + +This flag forces the use of frame pointers. It takes one of the following +values: + +* `y`, `yes`, `on`, or no value: Frame pointers are forced to be enabled. +* `n`, `no`, or `off`: Frame pointers are not forced to be enabled. This does + not necessarily mean frame pointers will be removed. + +The default if not specified depends on the target. + +## default-linker-libraries + +This flag controls whether or not the linker includes its default libraries. +It takes one of the following values: + +* `y`, `yes`, `on`, or no value: Default libraries are included. +* `n`, `no`, or `off`: Default libraries are **not** included. + +For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to +the linker. + +The default is `yes` if not specified. + +[option-emit]: ../command-line-arguments.md#option-emit +[option-o-optimize]: ../command-line-arguments.md#option-o-optimize [profile-guided optimization]: ../profile-guided-optimization.md +[option-g-debug]: ../command-line-arguments.md#option-g-debug diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index bdb3c51965..577d03d103 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -2,23 +2,26 @@ Here's a list of command-line arguments to `rustc` and what they do. + ## `-h`/`--help`: get help This flag will print out help information for `rustc`. + ## `--cfg`: configure the compilation environment -This flag can turn on or off various `#[cfg]` settings. +This flag can turn on or off various `#[cfg]` settings for [conditional +compilation](../reference/conditional-compilation.md). The value can either be a single identifier or two identifiers separated by `=`. For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively. + ## `-L`: add a directory to the library search path -When looking for external crates or libraries, a directory passed to this flag -will be searched. +The `-L` flag adds a path to search for external crates and libraries. The kind of search path can optionally be specified with the form `-L KIND=PATH` where `KIND` may be one of: @@ -31,6 +34,7 @@ KIND=PATH` where `KIND` may be one of: - `all` — Search for all library kinds in this directory. This is the default if `KIND` is not specified. + ## `-l`: link the generated crate to a native library This flag allows you to specify linking to a specific native library when building @@ -55,6 +59,7 @@ and `LINK_NAME` is the name of the actual library that will be linked. [link-attribute]: ../reference/items/external-blocks.html#the-link-attribute + ## `--crate-type`: a list of types of crates for the compiler to emit This instructs `rustc` on which crate type to build. This flag accepts a @@ -80,10 +85,12 @@ More details may be found in the [linkage chapter] of the reference. [linkage chapter]: ../reference/linkage.html [crate_type]: ../reference/linkage.html + ## `--crate-name`: specify the name of the crate being built This informs `rustc` of the name of your crate. + ## `--edition`: specify the edition to use This flag takes a value of `2015` or `2018`. The default is `2015`. More @@ -91,8 +98,8 @@ information about editions may be found in the [edition guide]. [edition guide]: ../edition-guide/introduction.html + ## `--emit`: specifies the types of output files to generate - This flag controls the types of output files generated by the compiler. It accepts a comma-separated list of values, and may be specified multiple times. @@ -117,22 +124,24 @@ The valid emit kinds are: - `obj` — Generates a native object file. The default output filename is `CRATE_NAME.o`. -The output filename can be set with the `-o` flag. A suffix may be added to -the filename with the `-C extra-filename` flag. The files are written to the -current directory unless the `--out-dir` flag is used. Each emission type may -also specify the output filename with the form `KIND=PATH`, which takes -precedence over the `-o` flag. +The output filename can be set with the [`-o` flag](#option-o-output). A +suffix may be added to the filename with the [`-C extra-filename` +flag](codegen-options/index.md#extra-filename). The files are written to the +current directory unless the [`--out-dir` flag](#option-out-dir) is used. Each +emission type may also specify the output filename with the form `KIND=PATH`, +which takes precedence over the `-o` flag. [LLVM bitcode]: https://llvm.org/docs/BitCodeFormat.html [LLVM IR]: https://llvm.org/docs/LangRef.html + ## `--print`: print compiler information This flag prints out various information about the compiler. This flag may be specified multiple times, and the information is printed in the order the flags are specified. Specifying a `--print` flag will usually disable the -`--emit` step and will only print the requested information. The valid types -of print values are: +[`--emit`](#option-emit) step and will only print the requested information. +The valid types of print values are: - `crate-name` — The name of the crate. - `file-names` — The names of the files created by the `link` emit kind. @@ -142,14 +151,17 @@ of print values are: - `target-list` — List of known targets. The target may be selected with the `--target` flag. - `target-cpus` — List of available CPU values for the current target. The - target CPU may be selected with the `-C target-cpu=val` flag. + target CPU may be selected with the [`-C target-cpu=val` + flag](codegen-options/index.md#target-cpu). - `target-features` — List of available target features for the current - target. Target features may be enabled with the `-C target-feature=val` - flag. This flag is unsafe. See [known issues](targets/known-issues.md) for more details. + target. Target features may be enabled with the [`-C target-feature=val` + flag](codegen-options/index.md#target-feature). This flag is unsafe. See + [known issues](targets/known-issues.md) for more details. - `relocation-models` — List of relocation models. Relocation models may be - selected with the `-C relocation-model=val` flag. + selected with the [`-C relocation-model=val` + flag](codegen-options/index.md#relocation-model). - `code-models` — List of code models. Code models may be selected with the - `-C code-model=val` flag. + [`-C code-model=val` flag](codegen-options/index.md#code-model). - `tls-models` — List of Thread Local Storage models supported. The model may be selected with the `-Z tls-model=val` flag. - `native-static-libs` — This may be used when creating a `staticlib` crate @@ -160,53 +172,65 @@ of print values are: [conditional compilation]: ../reference/conditional-compilation.html + ## `-g`: include debug information -A synonym for `-C debuginfo=2`, for more see [here](codegen-options/index.md#debuginfo). +A synonym for [`-C debuginfo=2`](codegen-options/index.md#debuginfo). + ## `-O`: optimize your code -A synonym for `-C opt-level=2`, for more see [here](codegen-options/index.md#opt-level). +A synonym for [`-C opt-level=2`](codegen-options/index.md#opt-level). + ## `-o`: filename of the output This flag controls the output filename. + ## `--out-dir`: directory to write the output in The outputted crate will be written to this directory. This flag is ignored if -the `-o` flag is used. +the [`-o` flag](#option-o-output) is used. + ## `--explain`: provide a detailed explanation of an error message Each error of `rustc`'s comes with an error code; this will print out a longer explanation of a given error. + ## `--test`: build a test harness When compiling this crate, `rustc` will ignore your `main` function and instead produce a test harness. + ## `--target`: select a target triple to build This controls which [target](targets/index.md) to produce. + ## `-W`: set lint warnings This flag will set which lints should be set to the [warn level](lints/levels.md#warn). + ## `-A`: set lint allowed This flag will set which lints should be set to the [allow level](lints/levels.md#allow). + ## `-D`: set lint denied This flag will set which lints should be set to the [deny level](lints/levels.md#deny). + ## `-F`: set lint forbidden This flag will set which lints should be set to the [forbid level](lints/levels.md#forbid). + ## `-Z`: set unstable options This flag will allow you to set unstable options of rustc. In order to set multiple options, @@ -214,35 +238,62 @@ the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time`. Specifying options with -Z is only available on nightly. To view all available options run: `rustc -Z help`. + ## `--cap-lints`: set the most restrictive lint level This flag lets you 'cap' lints, for more, [see here](lints/levels.md#capping-lints). + ## `-C`/`--codegen`: code generation options This flag will allow you to set [codegen options](codegen-options/index.md). + ## `-V`/`--version`: print a version This flag will print out `rustc`'s version. + ## `-v`/`--verbose`: use verbose output This flag, when combined with other flags, makes them produce extra output. + ## `--extern`: specify where an external library is located -This flag allows you to pass the name and location of an external crate that -will be linked into the crate you are building. This flag may be specified -multiple times. The format of the value should be `CRATENAME=PATH`. +This flag allows you to pass the name and location for an external crate of a +direct dependency. Indirect dependencies (dependencies of dependencies) are +located using the [`-L` flag](#option-l-search-path). The given crate name is +added to the [extern prelude], which is the same as specifying `extern crate` +within the root module. The given crate name does not need to match the name +the library was built with. +This flag may be specified multiple times. This flag takes an argument with +either of the following formats: + +* `CRATENAME=PATH` — Indicates the given crate is found at the given path. +* `CRATENAME` — Indicates the given crate may be found in the search path, + such as within the sysroot or via the `-L` flag. + +The same crate name may be specified multiple times for different crate types. +If both an `rlib` and `dylib` are found, an internal algorithm is used to +decide which to use for linking. The [`-C prefer-dynamic` +flag][prefer-dynamic] may be used to influence which is used. + +If the same crate name is specified with and without a path, the one with the +path is used and the pathless flag has no effect. + +[extern prelude]: ../reference/items/extern-crates.html#extern-prelude +[prefer-dynamic]: codegen-options/index.md#prefer-dynamic + + ## `--sysroot`: Override the system root The "sysroot" is where `rustc` looks for the crates that come with the Rust distribution; this flag allows that to be overridden. + ## `--error-format`: control how errors are produced - This flag lets you control the format of messages. Messages are printed to stderr. The valid options are: @@ -251,6 +302,7 @@ stderr. The valid options are: - `json` — Structured JSON output. See [the JSON chapter] for more detail. - `short` — Short, one-line messages. + ## `--color`: configure coloring of output This flag lets you control color settings of the output. The valid options @@ -260,6 +312,7 @@ are: - `always` — Always use colors. - `never` — Never colorize output. + ## `--remap-path-prefix`: remap source names in output Remap source path prefixes in all output, including compiler diagnostics, @@ -274,13 +327,14 @@ replacement is purely textual, with no consideration of the current system's pathname syntax. For example `--remap-path-prefix foo=bar` will match `foo/lib.rs` but not `./foo/lib.rs`. + ## `--json`: configure json messages printed by the compiler - -When the `--error-format=json` option is passed to rustc then all of the -compiler's diagnostic output will be emitted in the form of JSON blobs. The -`--json` argument can be used in conjunction with `--error-format=json` to -configure what the JSON blobs contain as well as which ones are emitted. +When the [`--error-format=json` option](#option-error-format) is passed to +rustc then all of the compiler's diagnostic output will be emitted in the form +of JSON blobs. The `--json` argument can be used in conjunction with +`--error-format=json` to configure what the JSON blobs contain as well as +which ones are emitted. With `--error-format=json` the compiler will always emit any compiler errors as a JSON blob, but the following options are also available to the `--json` flag @@ -296,20 +350,23 @@ to customize the output: indicates that the diagnostic should have embedded ANSI color codes intended to be used to colorize the message in the manner rustc typically already does for terminal outputs. Note that this is usefully combined with crates like - `fwdansi` to translate these ANSI codes on Windows to console commands or - `strip-ansi-escapes` if you'd like to optionally remove the ansi colors - afterwards. + [`fwdansi`](https://crates.io/crates/fwdansi) to translate these ANSI codes + on Windows to console commands or + [`strip-ansi-escapes`](https://crates.io/crates/strip-ansi-escapes) if you'd + like to optionally remove the ansi colors afterwards. - `artifacts` - this instructs rustc to emit a JSON blob for each artifact that - is emitted. An artifact corresponds to a request from the `--emit` CLI - argument, and as soon as the artifact is available on the filesystem a - notification will be emitted. + is emitted. An artifact corresponds to a request from the [`--emit` CLI + argument](#option-emit), and as soon as the artifact is available on the + filesystem a notification will be emitted. -Note that it is invalid to combine the `--json` argument with the `--color` -argument, and it is required to combine `--json` with `--error-format=json`. +Note that it is invalid to combine the `--json` argument with the +[`--color`](#option-color) argument, and it is required to combine `--json` +with `--error-format=json`. See [the JSON chapter] for more detail. + ## `@path`: load command-line flags from a path If you specify `@path` on the command-line, then it will open `path` and read diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 834a4a7972..2944e86566 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -35,7 +35,7 @@ talk about later in this section. ## warn The 'warn' lint level will produce a warning if you violate the lint. For example, -this code runs afoul of the `unused_variable` lint: +this code runs afoul of the `unused_variables` lint: ```rust pub fn foo() { diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index 5688e90ada..dc5a9e44ac 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -45,53 +45,6 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type` = note: for more information, see issue #36887 ``` -## legacy-constructor-visibility - -[RFC 1506](https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md) modified some -visibility rules, and changed the visibility of struct constructors. Some -example code that triggers this lint: - -```rust,ignore -mod m { - pub struct S(u8); - - fn f() { - // this is trying to use S from the 'use' line, but because the `u8` is - // not pub, it is private - ::S; - } -} - -use m::S; -``` - -This will produce: - -```text -error: private struct constructors are not usable through re-exports in outer modules - --> src/main.rs:5:9 - | -5 | ::S; - | ^^^ - | - = note: `#[deny(legacy_constructor_visibility)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #39207 -``` - - -## legacy-directory-ownership - -The legacy_directory_ownership warning is issued when - -* There is a non-inline module with a `#[path]` attribute (e.g. `#[path = "foo.rs"] mod bar;`), -* The module's file ("foo.rs" in the above example) is not named "mod.rs", and -* The module's file contains a non-inline child module without a `#[path]` attribute. - -The warning can be fixed by renaming the parent module to "mod.rs" and moving -it into its own directory if appropriate. - - ## missing-fragment-specifier The missing_fragment_specifier warning is issued when an unused pattern in a @@ -169,39 +122,49 @@ error: literal out of range for u8 | ``` -## parenthesized-params-in-types-and-modules +## patterns-in-fns-without-body -This lint detects incorrect parentheses. Some example code that triggers this -lint: +This lint detects patterns in functions without body were that were +previously erroneously allowed. Some example code that triggers this lint: -```rust,ignore -let x = 5 as usize(); +```rust,compile_fail +trait Trait { + fn foo(mut arg: u8); +} ``` This will produce: ```text -error: parenthesized parameters may only be used with a trait - --> src/main.rs:2:21 +warning: patterns aren't allowed in methods without bodies + --> src/main.rs:2:12 | -2 | let x = 5 as usize(); - | ^^ +2 | fn foo(mut arg: u8); + | ^^^^^^^ | - = note: `#[deny(parenthesized_params_in_types_and_modules)]` on by default + = note: `#[warn(patterns_in_fns_without_body)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #42238 + = note: for more information, see issue #35203 ``` -To fix it, remove the `()`s. +To fix this, remove the pattern; it can be used in the implementation without +being used in the definition. That is: -## pub-use-of-private-extern-crate +```rust +trait Trait { + fn foo(arg: u8); +} -This lint detects a specific situation of re-exporting a private `extern crate`; +impl Trait for i32 { + fn foo(mut arg: u8) { + + } +} +``` -## safe-extern-statics +## pub-use-of-private-extern-crate -In older versions of Rust, there was a soundness issue where `extern static`s were allowed -to be accessed in safe code. This lint now catches and denies this kind of code. +This lint detects a specific situation of re-exporting a private `extern crate`; ## unknown-crate-types diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index 813d7c4baf..386f6008d0 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -307,58 +307,6 @@ warning: path statement with no effect | ``` -## patterns-in-fns-without-body - -This lint detects patterns in functions without body were that were -previously erroneously allowed. Some example code that triggers this lint: - -```rust -trait Trait { - fn foo(mut arg: u8); -} -``` - -This will produce: - -```text -warning: patterns aren't allowed in methods without bodies - --> src/main.rs:2:12 - | -2 | fn foo(mut arg: u8); - | ^^^^^^^ - | - = note: `#[warn(patterns_in_fns_without_body)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #35203 -``` - -To fix this, remove the pattern; it can be used in the implementation without -being used in the definition. That is: - -```rust -trait Trait { - fn foo(arg: u8); -} - -impl Trait for i32 { - fn foo(mut arg: u8) { - - } -} -``` - -## plugin-as-library - -This lint detects when compiler plugins are used as ordinary library in -non-plugin crate. Some example code that triggers this lint: - -```rust,ignore -#![feature(plugin)] -#![plugin(macro_crate_test)] - -extern crate macro_crate_test; -``` - ## private-in-public This lint detects private items in public interfaces not caught by the old implementation. Some diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 46528187c1..f982863e67 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -1,8 +1,11 @@ # The Rustdoc Book - [What is rustdoc?](what-is-rustdoc.md) +- [How to write documentation](how-to-write-documentation.md) - [Command-line arguments](command-line-arguments.md) - [The `#[doc]` attribute](the-doc-attribute.md) - [Documentation tests](documentation-tests.md) +- [Lints](lints.md) - [Passes](passes.md) +- [Advanced Features](advanced-features.md) - [Unstable features](unstable-features.md) diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md new file mode 100644 index 0000000000..47bef3cdde --- /dev/null +++ b/src/doc/rustdoc/src/advanced-features.md @@ -0,0 +1,34 @@ +# Advanced Features + +The features listed on this page fall outside the rest of the main categories. + +## `#[cfg(doc)]`: Documenting platform-/feature-specific information + +For conditional compilation, Rustdoc treats your crate the same way the compiler does: Only things +from the host target are available (or from the given `--target` if present), and everything else is +"filtered out" from the crate. This can cause problems if your crate is providing different things +on different targets and you want your documentation to reflect all the available items you +provide. + +If you want to make sure an item is seen by Rustdoc regardless of what platform it's targeting, +you can apply `#[cfg(doc)]` to it. Rustdoc sets this whenever it's building documentation, so +anything that uses that flag will make it into documentation it generates. To apply this to an item +with other `#[cfg]` filters on it, you can write something like `#[cfg(any(windows, doc))]`. +This will preserve the item either when built normally on Windows, or when being documented +anywhere. + +Please note that this feature is not passed to doctests. + +Example: + +```rust +/// Token struct that can only be used on Windows. +#[cfg(any(windows, doc))] +pub struct WindowsToken; +/// Token struct that can only be used on Unix. +#[cfg(any(unix, doc))] +pub struct UnixToken; +``` + +Here, the respective tokens can only be used by dependent crates on their respective platforms, but +they will both appear in documentation. diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index b21defaedc..2e32ce31ec 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -355,7 +355,38 @@ $ rustdoc src/lib.rs --edition 2018 $ rustdoc --test src/lib.rs --edition 2018 ``` -This flag allows rustdoc to treat your rust code as the given edition. It will compile doctests with +This flag allows `rustdoc` to treat your rust code as the given edition. It will compile doctests with the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015` (the first edition). +## `--theme`: add a theme to the documentation output + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs --theme /path/to/your/custom-theme.css +``` + +`rustdoc`'s default output includes two themes: `light` (the default) and +`dark`. This flag allows you to add custom themes to the output. Giving a CSS +file to this flag adds it to your documentation as an additional theme choice. +The theme's name is determined by its filename; a theme file named +`custom-theme.css` will add a theme named `custom-theme` to the documentation. + +## `--check-theme`: verify custom themes against the default theme + +Using this flag looks like this: + +```bash +$ rustdoc --check-theme /path/to/your/custom-theme.css +``` + +While `rustdoc`'s HTML output is more-or-less consistent between versions, there +is no guarantee that a theme file will have the same effect. The `--theme` flag +will still allow you to add the theme to your documentation, but to ensure that +your theme works as expected, you can use this flag to verify that it implements +the same CSS rules as the official `light` theme. + +`--check-theme` is a separate mode in `rustdoc`. When `rustdoc` sees the +`--check-theme` flag, it discards all other flags and only performs the CSS rule +comparison operation. diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index bc1da5ff15..96fa4344b0 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -1,7 +1,7 @@ # Documentation tests `rustdoc` supports executing your documentation examples as tests. This makes sure -that your tests are up to date and working. +that examples within your documentation are up to date and working. The basic idea is this: diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md new file mode 100644 index 0000000000..dd3aa5d4b6 --- /dev/null +++ b/src/doc/rustdoc/src/how-to-write-documentation.md @@ -0,0 +1,82 @@ +# How to write documentation + +This chapter covers not only how to write documentation but specifically +how to write **good** documentation. Something to keep in mind when +writing documentation is that your audience is not just yourself but others +who simply don't have the context you do. It is important to be as clear +as you can, and as complete as possible. As a rule of thumb: the more +documentation you write for your crate the better. If an item is public +then it should be documented. + +## Basic structure + +It is recommended that each item's documentation follows this basic structure: + +```text +[short sentence explaining what it is] + +[more detailed explanation] + +[at least one code example that users can copy/paste to try it] + +[even more advanced explanations if necessary] +``` + +This basic structure should be straightforward to follow when writing your +documentation and, while you might think that a code example is trivial, +the examples are really important because they can help your users to +understand what an item is, how it is used, and for what purpose it exists. + +Let's see an example coming from the [standard library] by taking a look at the +[`std::env::args()`][env::args] function: + +``````text +Returns the arguments which this program was started with (normally passed +via the command line). + +The first element is traditionally the path of the executable, but it can be +set to arbitrary text, and may not even exist. This means this property should +not be relied upon for security purposes. + +On Unix systems shell usually expands unquoted arguments with glob patterns +(such as `*` and `?`). On Windows this is not done, and such arguments are +passed as-is. + +# Panics + +The returned iterator will panic during iteration if any argument to the +process is not valid unicode. If this is not desired, +use the [`args_os`] function instead. + +# Examples + +``` +use std::env; + +// Prints each argument on a separate line +for argument in env::args() { + println!("{}", argument); +} +``` + +[`args_os`]: ./fn.args_os.html +`````` + +As you can see, it follows the structure detailed above: it starts with a short +sentence explaining what the functions does, then it provides more information +and finally provides a code example. + +## Markdown + +`rustdoc` is using the [commonmark markdown specification]. You might be +interested into taking a look at their website to see what's possible to do. + +## Lints + +To be sure that you didn't miss any item without documentation or code examples, +you can take a look at the rustdoc lints [here][rustdoc-lints]. + +[standard library]: https://doc.rust-lang.org/stable/std/index.html +[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html +[commonmark markdown specification]: https://commonmark.org/ +[rustdoc-lints]: lints.md diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md new file mode 100644 index 0000000000..beb2556872 --- /dev/null +++ b/src/doc/rustdoc/src/lints.md @@ -0,0 +1,119 @@ +# Lints + +`rustdoc` provides lints to help you writing and testing your documentation. You +can use them like any other lints by doing this: + +```rust,ignore +#![allow(missing_docs)] // allowing the lint, no message +#![warn(missing_docs)] // warn if there is missing docs +#![deny(missing_docs)] // rustdoc will fail if there is missing docs +``` + +Here is the list of the lints provided by `rustdoc`: + +## intra_doc_link_resolution_failure + +This lint **warns by default** and is **nightly-only**. This lint detects when +an intra-doc link fails to get resolved. For example: + +```rust +/// I want to link to [`Inexistent`] but it doesn't exist! +pub fn foo() {} +``` + +You'll get a warning saying: + +```text +error: `[`Inexistent`]` cannot be resolved, ignoring it... +``` + +## missing_docs + +This lint is **allowed by default**. It detects items missing documentation. +For example: + +```rust +#![warn(missing_docs)] + +pub fn undocumented() {} +# fn main() {} +``` + +The `undocumented` function will then have the following warning: + +```text +warning: missing documentation for a function + --> your-crate/lib.rs:3:1 + | + 3 | pub fn undocumented() {} + | ^^^^^^^^^^^^^^^^^^^^^ +``` + +## missing_doc_code_examples + +This lint is **allowed by default**. It detects when a documentation block +is missing a code example. For example: + +```rust +#![warn(missing_doc_code_examples)] + +/// There is no code example! +pub fn no_code_example() {} +# fn main() {} +``` + +The `no_code_example` function will then have the following warning: + +```text +warning: Missing code example in this documentation + --> your-crate/lib.rs:3:1 + | +LL | /// There is no code example! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +``` + +To fix the lint, you need to add a code example into the documentation block: + +```rust +/// There is no code example! +/// +/// ``` +/// println!("calling no_code_example..."); +/// no_code_example(); +/// println!("we called no_code_example!"); +/// ``` +pub fn no_code_example() {} +``` + +## private_doc_tests + +This lint is **allowed by default**. It detects documentation tests when they +are on a private item. For example: + +```rust +#![warn(private_doc_tests)] + +mod foo { + /// private doc test + /// + /// ``` + /// assert!(false); + /// ``` + fn bar() {} +} +# fn main() {} +``` + +Which will give: + +```text +warning: Documentation test in private item + --> your-crate/lib.rs:4:1 + | + 4 | / /// private doc test + 5 | | /// + 6 | | /// ``` + 7 | | /// assert!(false); + 8 | | /// ``` + | |___________^ +``` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 3c3e72aa37..a48526d39f 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -106,11 +106,11 @@ item, it will be accompanied by a banner explaining that the item is only availa platforms. For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently -running on. To aid this, Rustdoc sets the flag `#[cfg(rustdoc)]` when running on your crate. +running on. To aid this, Rustdoc sets the flag `#[cfg(doc)]` when running on your crate. Combining this with the target platform of a given item allows it to appear when building your crate normally on that platform, as well as when building documentation anywhere. -For example, `#[cfg(any(windows, rustdoc))]` will preserve the item either on Windows or during the +For example, `#[cfg(any(windows, doc))]` will preserve the item either on Windows or during the documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that the item is supposed to be used on Windows. For example: @@ -118,12 +118,12 @@ the item is supposed to be used on Windows. For example: #![feature(doc_cfg)] /// Token struct that can only be used on Windows. -#[cfg(any(windows, rustdoc))] +#[cfg(any(windows, doc))] #[doc(cfg(windows))] pub struct WindowsToken; /// Token struct that can only be used on Unix. -#[cfg(any(unix, rustdoc))] +#[cfg(any(unix, doc))] #[doc(cfg(unix))] pub struct UnixToken; ``` @@ -294,30 +294,6 @@ some consideration for their stability, and names that end in a number). Giving `rustdoc` will disable this sorting and instead make it print the items in the order they appear in the source. -### `--themes`: provide additional themes - -Using this flag looks like this: - -```bash -$ rustdoc src/lib.rs -Z unstable-options --themes theme.css -``` - -Giving this flag to `rustdoc` will make it copy your theme into the generated crate docs and enable -it in the theme selector. Note that `rustdoc` will reject your theme file if it doesn't style -everything the "light" theme does. See `--theme-checker` below for details. - -### `--theme-checker`: verify theme CSS for validity - -Using this flag looks like this: - -```bash -$ rustdoc -Z unstable-options --theme-checker theme.css -``` - -Before including your theme in crate docs, `rustdoc` will compare all the CSS rules it contains -against the "light" theme included by default. Using this flag will allow you to see which rules are -missing if `rustdoc` rejects your theme. - ### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs Using this flag looks like this: diff --git a/src/doc/unstable-book/src/language-features/cfg-sanitize.md b/src/doc/unstable-book/src/language-features/cfg-sanitize.md new file mode 100644 index 0000000000..949f24ab9c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/cfg-sanitize.md @@ -0,0 +1,36 @@ +# `cfg_sanitize` + +The tracking issue for this feature is: [#39699] + +[#39699]: https://github.com/rust-lang/rust/issues/39699 + +------------------------ + +The `cfg_sanitize` feature makes it possible to execute different code +depending on whether a particular sanitizer is enabled or not. + +## Examples + +``` rust +#![feature(cfg_sanitize)] + +#[cfg(sanitize = "thread")] +fn a() { + // ... +} + +#[cfg(not(sanitize = "thread"))] +fn a() { + // ... +} + +fn b() { + if cfg!(sanitize = "leak") { + // ... + } else { + // ... + } +} + +``` + diff --git a/src/doc/unstable-book/src/language-features/const-if-match.md b/src/doc/unstable-book/src/language-features/const-if-match.md new file mode 100644 index 0000000000..ee9cfcbd9d --- /dev/null +++ b/src/doc/unstable-book/src/language-features/const-if-match.md @@ -0,0 +1,14 @@ +# `const_if_match` + +The tracking issue for this feature is: [#49146] + +[#49146]: https://github.com/rust-lang/rust/issues/49146 + +------------------------ + +Allows for the use of conditionals (`if` and `match`) in a const context. +Const contexts include `static`, `static mut`, `const`, `const fn`, const +generics, and array initializers. Enabling this feature flag will also make +`&&` and `||` function normally in a const-context by removing the hack that +replaces them with their non-short-circuiting equivalents, `&` and `|`, in a +`const` or `static`. diff --git a/src/doc/unstable-book/src/language-features/doc-cfg.md b/src/doc/unstable-book/src/language-features/doc-cfg.md index 96c66a1515..e75f1aea99 100644 --- a/src/doc/unstable-book/src/language-features/doc-cfg.md +++ b/src/doc/unstable-book/src/language-features/doc-cfg.md @@ -13,7 +13,7 @@ This attribute has two effects: 2. The item's doc-tests will only run on the specific platform. In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a -special conditional compilation flag, `#[cfg(rustdoc)]`, set whenever building documentation on your +special conditional compilation flag, `#[cfg(doc)]`, set whenever building documentation on your crate. This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the @@ -22,7 +22,7 @@ standard library be documented. ```rust #![feature(doc_cfg)] -#[cfg(any(windows, rustdoc))] +#[cfg(any(windows, doc))] #[doc(cfg(windows))] /// The application's icon in the notification area (a.k.a. system tray). /// diff --git a/src/doc/unstable-book/src/language-features/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md deleted file mode 100644 index 8db241e4b4..0000000000 --- a/src/doc/unstable-book/src/language-features/on-unimplemented.md +++ /dev/null @@ -1,154 +0,0 @@ -# `on_unimplemented` - -The tracking issue for this feature is: [#29628] - -[#29628]: https://github.com/rust-lang/rust/issues/29628 - ------------------------- - -The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]` -attribute, which allows trait definitions to add specialized notes to error -messages when an implementation was expected but not found. You can refer -to the trait's generic arguments by name and to the resolved type using -`Self`. - -For example: - -```rust,compile_fail -#![feature(on_unimplemented)] - -#[rustc_on_unimplemented="an iterator over elements of type `{A}` \ - cannot be built from a collection of type `{Self}`"] -trait MyIterator { - fn next(&mut self) -> A; -} - -fn iterate_chars>(i: I) { - // ... -} - -fn main() { - iterate_chars(&[1, 2, 3][..]); -} -``` - -When the user compiles this, they will see the following; - -```txt -error[E0277]: the trait bound `&[{integer}]: MyIterator` is not satisfied - --> :14:5 - | -14 | iterate_chars(&[1, 2, 3][..]); - | ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]` - | - = help: the trait `MyIterator` is not implemented for `&[{integer}]` - = note: required by `iterate_chars` -``` - -`on_unimplemented` also supports advanced filtering for better targeting -of messages, as well as modifying specific parts of the error message. You -target the text of: - - - the main error message (`message`) - - the label (`label`) - - an extra note (`note`) - -For example, the following attribute - -```rust,compile_fail -#[rustc_on_unimplemented( - message="message", - label="label", - note="note" -)] -trait MyIterator { - fn next(&mut self) -> A; -} -``` - -Would generate the following output: - -```text -error[E0277]: message - --> :14:5 - | -14 | iterate_chars(&[1, 2, 3][..]); - | ^^^^^^^^^^^^^ label - | - = note: note - = help: the trait `MyIterator` is not implemented for `&[{integer}]` - = note: required by `iterate_chars` -``` - -To allow more targeted error messages, it is possible to filter the -application of these fields based on a variety of attributes when using -`on`: - - - `crate_local`: whether the code causing the trait bound to not be - fulfilled is part of the user's crate. This is used to avoid suggesting - code changes that would require modifying a dependency. - - Any of the generic arguments that can be substituted in the text can be - referred by name as well for filtering, like `Rhs="i32"`, except for - `Self`. - - `_Self`: to filter only on a particular calculated trait resolution, like - `Self="std::iter::Iterator"`. This is needed because `Self` is a - keyword which cannot appear in attributes. - - `direct`: user-specified rather than derived obligation. - - `from_method`: usable both as boolean (whether the flag is present, like - `crate_local`) or matching against a particular method. Currently used - for `try`. - - `from_desugaring`: usable both as boolean (whether the flag is present) - or matching against a particular desugaring. The desugaring is identified - with its variant name in the `DesugaringKind` enum. - -For example, the `Iterator` trait can be annotated in the following way: - -```rust,compile_fail -#[rustc_on_unimplemented( - on( - _Self="&str", - note="call `.chars()` or `.as_bytes()` on `{Self}" - ), - message="`{Self}` is not an iterator", - label="`{Self}` is not an iterator", - note="maybe try calling `.iter()` or a similar method" -)] -pub trait Iterator {} -``` - -Which would produce the following outputs: - -```text -error[E0277]: `Foo` is not an iterator - --> src/main.rs:4:16 - | -4 | for foo in Foo {} - | ^^^ `Foo` is not an iterator - | - = note: maybe try calling `.iter()` or a similar method - = help: the trait `std::iter::Iterator` is not implemented for `Foo` - = note: required by `std::iter::IntoIterator::into_iter` - -error[E0277]: `&str` is not an iterator - --> src/main.rs:5:16 - | -5 | for foo in "" {} - | ^^ `&str` is not an iterator - | - = note: call `.chars()` or `.bytes() on `&str` - = help: the trait `std::iter::Iterator` is not implemented for `&str` - = note: required by `std::iter::IntoIterator::into_iter` -``` - -If you need to filter on multiple attributes, you can use `all`, `any` or -`not` in the following way: - -```rust,compile_fail -#[rustc_on_unimplemented( - on( - all(_Self="&str", T="std::string::String"), - note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`" - ) -)] -pub trait From: Sized { /* ... */ } -``` diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 68877b4843..495cdee62c 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -13,7 +13,7 @@ This feature is part of "compiler plugins." It will often be used with the ------------------------ `rustc` can load compiler plugins, which are user-provided libraries that -extend the compiler's behavior with new syntax extensions, lint checks, etc. +extend the compiler's behavior with new lint checks, etc. A plugin is a dynamic library crate with a designated *registrar* function that registers extensions with `rustc`. Other crates can load these extensions using @@ -21,148 +21,15 @@ the crate attribute `#![plugin(...)]`. See the `rustc_driver::plugin` documentation for more about the mechanics of defining and loading a plugin. -If present, arguments passed as `#![plugin(foo(... args ...))]` are not -interpreted by rustc itself. They are provided to the plugin through the -`Registry`'s `args` method. - In the vast majority of cases, a plugin should *only* be used through `#![plugin]` and not through an `extern crate` item. Linking a plugin would pull in all of libsyntax and librustc as dependencies of your crate. This is -generally unwanted unless you are building another plugin. The -`plugin_as_library` lint checks these guidelines. +generally unwanted unless you are building another plugin. The usual practice is to put compiler plugins in their own crate, separate from any `macro_rules!` macros or ordinary Rust code meant to be used by consumers of a library. -# Syntax extensions - -Plugins can extend Rust's syntax in various ways. One kind of syntax extension -is the procedural macro. These are invoked the same way as [ordinary -macros](../../book/macros.md), but the expansion is performed by arbitrary Rust -code that manipulates syntax trees at -compile time. - -Let's write a plugin -[`roman_numerals.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/roman_numerals.rs) -that implements Roman numeral integer literals. - -```rust,ignore -#![crate_type="dylib"] -#![feature(plugin_registrar, rustc_private)] - -extern crate syntax; -extern crate syntax_pos; -extern crate rustc; -extern crate rustc_driver; - -use syntax::parse::token::{self, Token}; -use syntax::tokenstream::{TokenTree, TokenStream}; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; -use syntax_pos::Span; -use rustc_driver::plugin::Registry; - -fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream) - -> Box { - - static NUMERALS: &'static [(&'static str, usize)] = &[ - ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400), - ("C", 100), ("XC", 90), ("L", 50), ("XL", 40), - ("X", 10), ("IX", 9), ("V", 5), ("IV", 4), - ("I", 1)]; - - if args.len() != 1 { - cx.span_err( - sp, - &format!("argument should be a single identifier, but got {} arguments", args.len())); - return DummyResult::any(sp); - } - - let text = match args.into_trees().next().unwrap() { - TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(), - _ => { - cx.span_err(sp, "argument should be a single identifier"); - return DummyResult::any(sp); - } - }; - - let mut text = &*text; - let mut total = 0; - while !text.is_empty() { - match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) { - Some(&(rn, val)) => { - total += val; - text = &text[rn.len()..]; - } - None => { - cx.span_err(sp, "invalid Roman numeral"); - return DummyResult::any(sp); - } - } - } - - MacEager::expr(cx.expr_usize(sp, total)) -} - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_macro("rn", expand_rn); -} -``` - -Then we can use `rn!()` like any other macro: - -```rust,ignore -#![feature(plugin)] -#![plugin(roman_numerals)] - -fn main() { - assert_eq!(rn!(MMXV), 2015); -} -``` - -The advantages over a simple `fn(&str) -> u32` are: - -* The (arbitrarily complex) conversion is done at compile time. -* Input validation is also performed at compile time. -* It can be extended to allow use in patterns, which effectively gives - a way to define new literal syntax for any data type. - -In addition to procedural macros, you can define new -[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds -of extensions. See `Registry::register_syntax_extension` and the -`SyntaxExtension` struct. For a more involved macro example, see -[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). - - -## Tips and tricks - -You can use `syntax::parse` to turn token trees into -higher-level syntax elements like expressions: - -```rust,ignore -fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) - -> Box { - - let mut parser = cx.new_parser_from_tts(args); - - let expr: P = parser.parse_expr(); -``` - -Looking through [`libsyntax` parser -code](https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs) -will give you a feel for how the parsing infrastructure works. - -Keep the `Span`s of everything you parse, for better error reporting. You can -wrap `Spanned` around your custom data structures. - -Calling `ExtCtxt::span_fatal` will immediately abort compilation. It's better to -instead call `ExtCtxt::span_err` and return `DummyResult` so that the compiler -can continue and find further errors. - -To print syntax fragments for debugging, you can use `span_note` together with -`syntax::print::pprust::*_to_string`. - # Lint plugins Plugins can extend [Rust's lint diff --git a/src/doc/unstable-book/src/language-features/re-rebalance-coherence.md b/src/doc/unstable-book/src/language-features/re-rebalance-coherence.md deleted file mode 100644 index 1e74652a89..0000000000 --- a/src/doc/unstable-book/src/language-features/re-rebalance-coherence.md +++ /dev/null @@ -1,23 +0,0 @@ -# `re_rebalance_coherence` - -The tracking issue for this feature is: [#55437] - -[#55437]: https://github.com/rust-lang/rust/issues/55437 - ------------------------- - -The `re_rebalance_coherence` feature tweaks the rules regarding which trait -impls are allowed in crates. -The following rule is used: - -Given `impl Trait for T0`, an impl is valid only if at -least one of the following is true: -- `Trait` is a local trait -- All of - - At least one of the types `T0..=Tn` must be a local type. Let `Ti` be the - first such type. - - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti` (excluding - `Ti`) - - -See the [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2451-re-rebalancing-coherence.md) for details. diff --git a/src/etc/dec2flt_table.py b/src/etc/dec2flt_table.py old mode 100644 new mode 100755 index 2ffaf13dc8..85395d2ecd --- a/src/etc/dec2flt_table.py +++ b/src/etc/dec2flt_table.py @@ -111,14 +111,18 @@ def print_proper_powers(): print("pub const MIN_E: i16 = {};".format(MIN_E)) print("pub const MAX_E: i16 = {};".format(MAX_E)) print() + print("#[rustfmt::skip]") typ = "([u64; {0}], [i16; {0}])".format(len(powers)) - print("pub const POWERS: ", typ, " = ([", sep='') + print("pub const POWERS: ", typ, " = (", sep='') + print(" [") for z in powers: - print(" 0x{:x},".format(z.sig)) - print("], [") + print(" 0x{:x},".format(z.sig)) + print(" ],") + print(" [") for z in powers: - print(" {},".format(z.exp)) - print("]);") + print(" {},".format(z.exp)) + print(" ],") + print(");") def print_short_powers(num_bits, significand_size): @@ -127,6 +131,7 @@ def print_short_powers(num_bits, significand_size): max_e = int(ceil(log(max_sig, 5))) e_range = range(max_e) typ = "[f{}; {}]".format(num_bits, len(e_range)) + print("#[rustfmt::skip]") print("pub const F", num_bits, "_SHORT_POWERS: ", typ, " = [", sep='') for e in e_range: print(" 1e{},".format(e)) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index a6b09722e1..5da01b96fa 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -284,10 +284,20 @@ class RustStdVecPrinter(object): ("(len: %i, cap: %i)" % (length, cap))) def children(self): + saw_inaccessible = False (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val) gdb_ptr = data_ptr.get_wrapped_value() for index in xrange(0, length): - yield (str(index), (gdb_ptr + index).dereference()) + if saw_inaccessible: + return + try: + # rust-lang/rust#64343: passing deref expr to `str` allows + # catching exception on garbage pointer + str((gdb_ptr + index).dereference()) + yield (str(index), (gdb_ptr + index).dereference()) + except RuntimeError: + saw_inaccessible = True + yield (str(index), "inaccessible") class RustStdVecDequePrinter(object): diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index 66a3c8e555..39c24fb10e 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -14,8 +14,7 @@ TEST_DIR = os.path.abspath( os.path.join(os.path.dirname(__file__), '../test/ui/derives/')) TEMPLATE = """\ -// ignore-x86 -// ^ due to stderr output differences +// ignore-x86 FIXME: missing sysroot spans (#53081) // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' {error_deriving} diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis new file mode 100644 index 0000000000..b3fc3d17af --- /dev/null +++ b/src/etc/natvis/libstd.natvis @@ -0,0 +1,102 @@ + + + + + + {{ size={base.table.items} }} + + base.table.items + base.table.items + base.table.growth_left + + + + + base.table.items + + + + + n-- + base.table.data.pointer[i].__1 + + i++ + + + + + + + {{ size={map.base.table.items} }} + + map.base.table.items + map.base.table.items + map.base.table.growth_left + + + + + map.base.table.items + + + + + n-- + map.base.table.data.pointer[i].__0 + + i++ + + + + + + + + {{ size={items} }} + + items + items + growth_left + + + + + items + + + + + n-- + data.pointer[i] + + i++ + + + + + diff --git a/src/liballoc/alloc/tests.rs b/src/liballoc/alloc/tests.rs index c69f4e49ee..c902971638 100644 --- a/src/liballoc/alloc/tests.rs +++ b/src/liballoc/alloc/tests.rs @@ -1,15 +1,15 @@ use super::*; extern crate test; -use test::Bencher; use crate::boxed::Box; +use test::Bencher; #[test] fn allocate_zeroed() { unsafe { let layout = Layout::from_size_align(1024, 1).unwrap(); - let ptr = Global.alloc_zeroed(layout.clone()) - .unwrap_or_else(|_| handle_alloc_error(layout)); + let ptr = + Global.alloc_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout)); let mut i = ptr.cast::().as_ptr(); let end = i.add(layout.size()); @@ -22,7 +22,7 @@ fn allocate_zeroed() { } #[bench] -#[cfg(not(miri))] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // Miri does not support benchmarks fn alloc_owned_small(b: &mut Bencher) { b.iter(|| { let _: Box<_> = box 10; diff --git a/src/liballoc/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs index 4c17bdc3e9..eb5f51d9ad 100644 --- a/src/liballoc/benches/btree/map.rs +++ b/src/liballoc/benches/btree/map.rs @@ -1,12 +1,12 @@ +use std::collections::BTreeMap; use std::iter::Iterator; use std::vec::Vec; -use std::collections::BTreeMap; -use rand::{Rng, seq::SliceRandom, thread_rng}; -use test::{Bencher, black_box}; +use rand::{seq::SliceRandom, thread_rng, Rng}; +use test::{black_box, Bencher}; macro_rules! map_insert_rand_bench { - ($name: ident, $n: expr, $map: ident) => ( + ($name: ident, $n: expr, $map: ident) => { #[bench] pub fn $name(b: &mut Bencher) { let n: usize = $n; @@ -27,11 +27,11 @@ macro_rules! map_insert_rand_bench { }); black_box(map); } - ) + }; } macro_rules! map_insert_seq_bench { - ($name: ident, $n: expr, $map: ident) => ( + ($name: ident, $n: expr, $map: ident) => { #[bench] pub fn $name(b: &mut Bencher) { let mut map = $map::new(); @@ -50,11 +50,11 @@ macro_rules! map_insert_seq_bench { }); black_box(map); } - ) + }; } macro_rules! map_find_rand_bench { - ($name: ident, $n: expr, $map: ident) => ( + ($name: ident, $n: expr, $map: ident) => { #[bench] pub fn $name(b: &mut Bencher) { let mut map = $map::new(); @@ -78,11 +78,11 @@ macro_rules! map_find_rand_bench { black_box(t); }) } - ) + }; } macro_rules! map_find_seq_bench { - ($name: ident, $n: expr, $map: ident) => ( + ($name: ident, $n: expr, $map: ident) => { #[bench] pub fn $name(b: &mut Bencher) { let mut map = $map::new(); @@ -101,20 +101,20 @@ macro_rules! map_find_seq_bench { black_box(x); }) } - ) + }; } -map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} -map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} +map_insert_rand_bench! {insert_rand_100, 100, BTreeMap} +map_insert_rand_bench! {insert_rand_10_000, 10_000, BTreeMap} -map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} -map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} +map_insert_seq_bench! {insert_seq_100, 100, BTreeMap} +map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap} -map_find_rand_bench!{find_rand_100, 100, BTreeMap} -map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} +map_find_rand_bench! {find_rand_100, 100, BTreeMap} +map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap} -map_find_seq_bench!{find_seq_100, 100, BTreeMap} -map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} +map_find_seq_bench! {find_seq_100, 100, BTreeMap} +map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap} fn bench_iter(b: &mut Bencher, size: i32) { let mut map = BTreeMap::::new(); @@ -145,3 +145,28 @@ pub fn iter_1000(b: &mut Bencher) { pub fn iter_100000(b: &mut Bencher) { bench_iter(b, 100000); } + +fn bench_first_and_last(b: &mut Bencher, size: i32) { + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + b.iter(|| { + for _ in 0..10 { + black_box(map.first_key_value()); + black_box(map.last_key_value()); + } + }); +} + +#[bench] +pub fn first_and_last_0(b: &mut Bencher) { + bench_first_and_last(b, 0); +} + +#[bench] +pub fn first_and_last_100(b: &mut Bencher) { + bench_first_and_last(b, 100); +} + +#[bench] +pub fn first_and_last_10k(b: &mut Bencher) { + bench_first_and_last(b, 10_000); +} diff --git a/src/liballoc/benches/btree/set.rs b/src/liballoc/benches/btree/set.rs index 6357ea3ea1..18502ded30 100644 --- a/src/liballoc/benches/btree/set.rs +++ b/src/liballoc/benches/btree/set.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use rand::{thread_rng, Rng}; -use test::{black_box, Bencher}; +use test::Bencher; fn random(n: usize) -> BTreeSet { let mut rng = thread_rng(); @@ -31,7 +31,6 @@ fn pos(n: usize) -> BTreeSet { set } - fn stagger(n1: usize, factor: usize) -> [BTreeSet; 2] { let n2 = n1 * factor; let mut sets = [BTreeSet::new(), BTreeSet::new()]; @@ -52,10 +51,7 @@ macro_rules! set_bench { let sets = $sets; // measure - b.iter(|| { - let x = sets[0].$set_func(&sets[1]).$result_func(); - black_box(x); - }) + b.iter(|| sets[0].$set_func(&sets[1]).$result_func()) } }; } diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index 4bf5ec10c4..9acda88606 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -1,3 +1,4 @@ +#![feature(map_first_last)] #![feature(repr_simd)] #![feature(test)] diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index ef91d801dc..e20c043286 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -1,9 +1,9 @@ use std::{mem, ptr}; +use rand::distributions::{Alphanumeric, Standard}; use rand::{thread_rng, Rng, SeedableRng}; -use rand::distributions::{Standard, Alphanumeric}; use rand_xorshift::XorShiftRng; -use test::{Bencher, black_box}; +use test::{black_box, Bencher}; #[bench] fn iterator(b: &mut Bencher) { @@ -239,7 +239,7 @@ macro_rules! sort { b.iter(|| v.clone().$f()); b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } - } + }; } macro_rules! sort_strings { @@ -251,7 +251,7 @@ macro_rules! sort_strings { b.iter(|| v.clone().$f()); b.bytes = $len * mem::size_of::<&str>() as u64; } - } + }; } macro_rules! sort_expensive { @@ -273,7 +273,7 @@ macro_rules! sort_expensive { }); b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } - } + }; } macro_rules! sort_lexicographic { @@ -284,7 +284,7 @@ macro_rules! sort_lexicographic { b.iter(|| v.clone().$f(|x| x.to_string())); b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64; } - } + }; } sort!(sort, sort_small_ascending, gen_ascending, 10); @@ -325,24 +325,25 @@ macro_rules! reverse { fn $name(b: &mut Bencher) { // odd length and offset by 1 to be as unaligned as possible let n = 0xFFFFF; - let mut v: Vec<_> = - (0..1+(n / mem::size_of::<$ty>() as u64)) - .map($f) - .collect(); + let mut v: Vec<_> = (0..1 + (n / mem::size_of::<$ty>() as u64)).map($f).collect(); b.iter(|| black_box(&mut v[1..]).reverse()); b.bytes = n; } - } + }; } reverse!(reverse_u8, u8, |x| x as u8); reverse!(reverse_u16, u16, |x| x as u16); -reverse!(reverse_u8x3, [u8;3], |x| [x as u8, (x>>8) as u8, (x>>16) as u8]); +reverse!(reverse_u8x3, [u8; 3], |x| [x as u8, (x >> 8) as u8, (x >> 16) as u8]); reverse!(reverse_u32, u32, |x| x as u32); reverse!(reverse_u64, u64, |x| x as u64); reverse!(reverse_u128, u128, |x| x as u128); -#[repr(simd)] struct F64x4(f64, f64, f64, f64); -reverse!(reverse_simd_f64x4, F64x4, |x| { let x = x as f64; F64x4(x,x,x,x) }); +#[repr(simd)] +struct F64x4(f64, f64, f64, f64); +reverse!(reverse_simd_f64x4, F64x4, |x| { + let x = x as f64; + F64x4(x, x, x, x) +}); macro_rules! rotate { ($name:ident, $gen:expr, $len:expr, $mid:expr) => { @@ -350,32 +351,32 @@ macro_rules! rotate { fn $name(b: &mut Bencher) { let size = mem::size_of_val(&$gen(1)[0]); let mut v = $gen($len * 8 / size); - b.iter(|| black_box(&mut v).rotate_left(($mid*8+size-1)/size)); + b.iter(|| black_box(&mut v).rotate_left(($mid * 8 + size - 1) / size)); b.bytes = (v.len() * size) as u64; } - } + }; } rotate!(rotate_tiny_by1, gen_random, 16, 1); -rotate!(rotate_tiny_half, gen_random, 16, 16/2); -rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16/2+1); +rotate!(rotate_tiny_half, gen_random, 16, 16 / 2); +rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16 / 2 + 1); rotate!(rotate_medium_by1, gen_random, 9158, 1); rotate!(rotate_medium_by727_u64, gen_random, 9158, 727); rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727); rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727); -rotate!(rotate_medium_half, gen_random, 9158, 9158/2); -rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158/2+1); +rotate!(rotate_medium_half, gen_random, 9158, 9158 / 2); +rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158 / 2 + 1); // Intended to use more RAM than the machine has cache -rotate!(rotate_huge_by1, gen_random, 5*1024*1024, 1); -rotate!(rotate_huge_by9199_u64, gen_random, 5*1024*1024, 9199); -rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5*1024*1024, 9199); -rotate!(rotate_huge_by9199_strings, gen_strings, 5*1024*1024, 9199); -rotate!(rotate_huge_by9199_big, gen_big_random, 5*1024*1024, 9199); -rotate!(rotate_huge_by1234577_u64, gen_random, 5*1024*1024, 1234577); -rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5*1024*1024, 1234577); -rotate!(rotate_huge_by1234577_strings, gen_strings, 5*1024*1024, 1234577); -rotate!(rotate_huge_by1234577_big, gen_big_random, 5*1024*1024, 1234577); -rotate!(rotate_huge_half, gen_random, 5*1024*1024, 5*1024*1024/2); -rotate!(rotate_huge_half_plus_one, gen_random, 5*1024*1024, 5*1024*1024/2+1); +rotate!(rotate_huge_by1, gen_random, 5 * 1024 * 1024, 1); +rotate!(rotate_huge_by9199_u64, gen_random, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by9199_strings, gen_strings, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by9199_big, gen_big_random, 5 * 1024 * 1024, 9199); +rotate!(rotate_huge_by1234577_u64, gen_random, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_by1234577_strings, gen_strings, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_by1234577_big, gen_big_random, 5 * 1024 * 1024, 1234577); +rotate!(rotate_huge_half, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2); +rotate!(rotate_huge_half_plus_one, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2 + 1); diff --git a/src/liballoc/benches/str.rs b/src/liballoc/benches/str.rs index 7f8661bd96..391475bc0c 100644 --- a/src/liballoc/benches/str.rs +++ b/src/liballoc/benches/str.rs @@ -1,4 +1,4 @@ -use test::{Bencher, black_box}; +use test::{black_box, Bencher}; #[bench] fn char_iterator(b: &mut Bencher) { @@ -12,7 +12,9 @@ fn char_iterator_for(b: &mut Bencher) { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; b.iter(|| { - for ch in s.chars() { black_box(ch); } + for ch in s.chars() { + black_box(ch); + } }); } @@ -40,7 +42,9 @@ fn char_iterator_rev_for(b: &mut Bencher) { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; b.iter(|| { - for ch in s.chars().rev() { black_box(ch); } + for ch in s.chars().rev() { + black_box(ch); + } }); } @@ -79,7 +83,9 @@ fn split_ascii(b: &mut Bencher) { fn split_extern_fn(b: &mut Bencher) { let s = "Mary had a little lamb, Little lamb, little-lamb."; let len = s.split(' ').count(); - fn pred(c: char) -> bool { c == ' ' } + fn pred(c: char) -> bool { + c == ' ' + } b.iter(|| assert_eq!(s.split(pred).count(), len)); } @@ -185,16 +191,19 @@ fn bench_contains_equal(b: &mut Bencher) { }) } - macro_rules! make_test_inner { ($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => { #[bench] fn $name(bencher: &mut Bencher) { let mut $s = $str; black_box(&mut $s); - bencher.iter(|| for _ in 0..$iters { black_box($code); }); + bencher.iter(|| { + for _ in 0..$iters { + black_box($code); + } + }); } - } + }; } macro_rules! make_test { @@ -261,15 +270,9 @@ make_test!(match_indices_a_str, s, s.match_indices("a").count()); make_test!(split_a_str, s, s.split("a").count()); -make_test!(trim_ascii_char, s, { - s.trim_matches(|c: char| c.is_ascii()) -}); -make_test!(trim_start_ascii_char, s, { - s.trim_start_matches(|c: char| c.is_ascii()) -}); -make_test!(trim_end_ascii_char, s, { - s.trim_end_matches(|c: char| c.is_ascii()) -}); +make_test!(trim_ascii_char, s, { s.trim_matches(|c: char| c.is_ascii()) }); +make_test!(trim_start_ascii_char, s, { s.trim_start_matches(|c: char| c.is_ascii()) }); +make_test!(trim_end_ascii_char, s, { s.trim_end_matches(|c: char| c.is_ascii()) }); make_test!(find_underscore_char, s, s.find('_')); make_test!(rfind_underscore_char, s, s.rfind('_')); diff --git a/src/liballoc/benches/vec_deque.rs b/src/liballoc/benches/vec_deque.rs index 7d2d3cfa61..bf2dffd1e9 100644 --- a/src/liballoc/benches/vec_deque.rs +++ b/src/liballoc/benches/vec_deque.rs @@ -1,5 +1,5 @@ use std::collections::VecDeque; -use test::{Bencher, black_box}; +use test::{black_box, Bencher}; #[bench] fn bench_new(b: &mut Bencher) { diff --git a/src/liballoc/benches/vec_deque_append.rs b/src/liballoc/benches/vec_deque_append.rs index 78ec91d9e3..5825bdc355 100644 --- a/src/liballoc/benches/vec_deque_append.rs +++ b/src/liballoc/benches/vec_deque_append.rs @@ -30,8 +30,5 @@ fn main() { assert!(BENCH_N % 2 == 0); let median = (durations[(l / 2) - 1] + durations[l / 2]) / 2; - println!( - "\ncustom-bench vec_deque_append {:?} ns/iter\n", - median.as_nanos() - ); + println!("\ncustom-bench vec_deque_append {:?} ns/iter\n", median.as_nanos()); } diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index d2bdda83fa..fc96045196 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -195,14 +195,10 @@ impl Clone for Cow<'_, B> { } fn clone_from(&mut self, source: &Self) { - if let Owned(ref mut dest) = *self { - if let Owned(ref o) = *source { - o.borrow().clone_into(dest); - return; - } + match (self, source) { + (&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest), + (t, s) => *t = s.clone(), } - - *self = source.clone(); } } @@ -449,9 +445,7 @@ impl<'a> AddAssign<&'a str> for Cow<'a, str> { fn add_assign(&mut self, rhs: &'a str) { if self.is_empty() { *self = Cow::Borrowed(rhs) - } else if rhs.is_empty() { - return; - } else { + } else if !rhs.is_empty() { if let Cow::Borrowed(lhs) = *self { let mut s = String::with_capacity(lhs.len() + rhs.len()); s.push_str(lhs); @@ -467,9 +461,7 @@ impl<'a> AddAssign> for Cow<'a, str> { fn add_assign(&mut self, rhs: Cow<'a, str>) { if self.is_empty() { *self = rhs - } else if rhs.is_empty() { - return; - } else { + } else if !rhs.is_empty() { if let Cow::Borrowed(lhs) = *self { let mut s = String::with_capacity(lhs.len() + rhs.len()); s.push_str(lhs); diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 567b8ea722..1c39a3721f 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -61,7 +61,60 @@ //! T` obtained from [`Box::::into_raw`] may be deallocated using the //! [`Global`] allocator with [`Layout::for_value(&*value)`]. //! +//! So long as `T: Sized`, a `Box` is guaranteed to be represented +//! as a single pointer and is also ABI-compatible with C pointers +//! (i.e. the C type `T*`). This means that if you have extern "C" +//! Rust functions that will be called from C, you can define those +//! Rust functions using `Box` types, and use `T*` as corresponding +//! type on the C side. As an example, consider this C header which +//! declares functions that create and destroy some kind of `Foo` +//! value: //! +//! ```c +//! /* C header */ +//! +//! /* Returns ownership to the caller */ +//! struct Foo* foo_new(void); +//! +//! /* Takes ownership from the caller; no-op when invoked with NULL */ +//! void foo_delete(struct Foo*); +//! ``` +//! +//! These two functions might be implemented in Rust as follows. Here, the +//! `struct Foo*` type from C is translated to `Box`, which captures +//! the ownership constraints. Note also that the nullable argument to +//! `foo_delete` is represented in Rust as `Option>`, since `Box` +//! cannot be null. +//! +//! ``` +//! #[repr(C)] +//! pub struct Foo; +//! +//! #[no_mangle] +//! pub extern "C" fn foo_new() -> Box { +//! Box::new(Foo) +//! } +//! +//! #[no_mangle] +//! pub extern "C" fn foo_delete(_: Option>) {} +//! ``` +//! +//! Even though `Box` has the same representation and C ABI as a C pointer, +//! this does not mean that you can convert an arbitrary `T*` into a `Box` +//! and expect things to work. `Box` values will always be fully aligned, +//! non-null pointers. Moreover, the destructor for `Box` will attempt to +//! free the value with the global allocator. In general, the best practice +//! is to only use `Box` for pointers that originated from the global +//! allocator. +//! +//! **Important.** At least at present, you should avoid using +//! `Box` types for functions that are defined in C but invoked +//! from Rust. In those cases, you should directly mirror the C types +//! as closely as possible. Using types like `Box` where the C +//! definition is just using `T*` can lead to undefined behavior, as +//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198]. +//! +//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198 //! [dereferencing]: ../../std/ops/trait.Deref.html //! [`Box`]: struct.Box.html //! [`Box`]: struct.Box.html @@ -152,6 +205,33 @@ impl Box { Box(ptr.cast().into()) } + /// Constructs a new `Box` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let zero = Box::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed() -> Box> { + unsafe { + let mut uninit = Self::new_uninit(); + ptr::write_bytes::(uninit.as_mut_ptr(), 0, 1); + uninit + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 83fd4485f7..5b48b594ff 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -598,6 +598,121 @@ impl BTreeMap { } } + /// Returns the first key-value pair in the map. + /// The key in this pair is the minimum key in the map. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.first_key_value(), None); + /// map.insert(1, "b"); + /// map.insert(2, "a"); + /// assert_eq!(map.first_key_value(), Some((&1, &"b"))); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn first_key_value(&self) -> Option<(&K, &V)> + where T: Ord, K: Borrow + { + let front = first_leaf_edge(self.root.as_ref()); + front.right_kv().ok().map(Handle::into_kv) + } + + /// Returns the first entry in the map for in-place manipulation. + /// The key of this entry is the minimum key in the map. + /// + /// # Examples + /// + /// Contrived way to `clear` a map: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// while let Some(entry) = map.first_entry() { + /// let (key, val) = entry.remove_entry(); + /// assert!(!map.contains_key(&key)); + /// } + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn first_entry(&mut self) -> Option> + where T: Ord, K: Borrow + { + match self.length { + 0 => None, + _ => Some(OccupiedEntry { + handle: self.root.as_mut().first_kv(), + length: &mut self.length, + _marker: PhantomData, + }), + } + } + + /// Returns the last key-value pair in the map. + /// The key in this pair is the maximum key in the map. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "b"); + /// map.insert(2, "a"); + /// assert_eq!(map.last_key_value(), Some((&2, &"a"))); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn last_key_value(&self) -> Option<(&K, &V)> + where T: Ord, K: Borrow + { + let back = last_leaf_edge(self.root.as_ref()); + back.left_kv().ok().map(Handle::into_kv) + } + + /// Returns the last entry in the map for in-place manipulation. + /// The key of this entry is the maximum key in the map. + /// + /// # Examples + /// + /// Contrived way to `clear` a map: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// while let Some(entry) = map.last_entry() { + /// let (key, val) = entry.remove_entry(); + /// assert!(!map.contains_key(&key)); + /// } + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn last_entry(&mut self) -> Option> + where T: Ord, K: Borrow + { + match self.length { + 0 => None, + _ => Some(OccupiedEntry { + handle: self.root.as_mut().last_kv(), + length: &mut self.length, + _marker: PhantomData, + }), + } + } + /// Returns `true` if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but the ordering diff --git a/src/liballoc/collections/btree/mod.rs b/src/liballoc/collections/btree/mod.rs index 8b7dc07063..f73a24d099 100644 --- a/src/liballoc/collections/btree/mod.rs +++ b/src/liballoc/collections/btree/mod.rs @@ -1,6 +1,6 @@ +pub mod map; mod node; mod search; -pub mod map; pub mod set; #[doc(hidden)] diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 0b5a271dbe..ab010b35f6 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -596,7 +596,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { // (We might be one-past-the-end, but that is allowed by LLVM.) // Getting the pointer is tricky though. `NodeHeader` does not have a `keys` // field because we want its size to not depend on the alignment of `K` - // (needed becuase `as_header` should be safe). We cannot call `as_leaf` + // (needed because `as_header` should be safe). We cannot call `as_leaf` // because we might be the shared root. // For this reason, `NodeHeader` has this `K2` parameter (that's usually `()` // and hence just adds a size-0-align-1 field, not affecting layout). diff --git a/src/liballoc/collections/btree/search.rs b/src/liballoc/collections/btree/search.rs index dfb67d2ea5..3f3c49a2ef 100644 --- a/src/liballoc/collections/btree/search.rs +++ b/src/liballoc/collections/btree/search.rs @@ -1,21 +1,23 @@ use core::borrow::Borrow; use core::cmp::Ordering; -use super::node::{Handle, NodeRef, marker, ForceResult::*}; +use super::node::{marker, ForceResult::*, Handle, NodeRef}; use SearchResult::*; pub enum SearchResult { Found(Handle, marker::KV>), - GoDown(Handle, marker::Edge>) + GoDown(Handle, marker::Edge>), } pub fn search_tree( mut node: NodeRef, - key: &Q + key: &Q, ) -> SearchResult - where Q: Ord, K: Borrow { - +where + Q: Ord, + K: Borrow, +{ loop { match search_node(node, key) { Found(handle) => return Found(handle), @@ -25,38 +27,38 @@ pub fn search_tree( node = internal.descend(); continue; } - } + }, } } } pub fn search_node( node: NodeRef, - key: &Q + key: &Q, ) -> SearchResult - where Q: Ord, K: Borrow { - +where + Q: Ord, + K: Borrow, +{ match search_linear(&node, key) { - (idx, true) => Found( - Handle::new_kv(node, idx) - ), - (idx, false) => SearchResult::GoDown( - Handle::new_edge(node, idx) - ) + (idx, true) => Found(Handle::new_kv(node, idx)), + (idx, false) => SearchResult::GoDown(Handle::new_edge(node, idx)), } } pub fn search_linear( node: &NodeRef, - key: &Q + key: &Q, ) -> (usize, bool) - where Q: Ord, K: Borrow { - +where + Q: Ord, + K: Borrow, +{ for (i, k) in node.keys().iter().enumerate() { match key.cmp(k.borrow()) { - Ordering::Greater => {}, + Ordering::Greater => {} Ordering::Equal => return (i, true), - Ordering::Less => return (i, false) + Ordering::Less => return (i, false), } } (node.keys().len(), false) diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index f0796354e0..85b93e0eda 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -194,16 +194,16 @@ pub struct Difference<'a, T: 'a> { #[derive(Debug)] enum DifferenceInner<'a, T: 'a> { Stitch { - // iterate all of self and some of other, spotting matches along the way + // iterate all of `self` and some of `other`, spotting matches along the way self_iter: Iter<'a, T>, other_iter: Peekable>, }, Search { - // iterate a small set, look up in the large set + // iterate `self`, look up in `other` self_iter: Iter<'a, T>, other_set: &'a BTreeSet, }, - Iterate(Iter<'a, T>), // simply stream self's elements + Iterate(Iter<'a, T>), // simply produce all values in `self` } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -356,7 +356,7 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = - (self.iter().next(), self.iter().next_back()) + (self.first(), self.last()) { (self_min, self_max) } else { @@ -365,7 +365,7 @@ impl BTreeSet { }; }; let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = - (other.iter().next(), other.iter().next_back()) + (other.first(), other.last()) { (other_min, other_max) } else { @@ -450,7 +450,7 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> { let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = - (self.iter().next(), self.iter().next_back()) + (self.first(), self.last()) { (self_min, self_max) } else { @@ -459,7 +459,7 @@ impl BTreeSet { }; }; let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = - (other.iter().next(), other.iter().next_back()) + (other.first(), other.last()) { (other_min, other_max) } else { @@ -625,14 +625,14 @@ impl BTreeSet { return false; } let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = - (self.iter().next(), self.iter().next_back()) + (self.first(), self.last()) { (self_min, self_max) } else { return true; // self is empty }; let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = - (other.iter().next(), other.iter().next_back()) + (other.first(), other.last()) { (other_min, other_max) } else { @@ -654,14 +654,12 @@ impl BTreeSet { Less => (), } if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - // Big difference in number of elements. for next in self_iter { if !other.contains(next) { return false; } } } else { - // Self is not much smaller than other set. let mut other_iter = other.iter(); other_iter.next(); other_iter.next_back(); @@ -702,6 +700,96 @@ impl BTreeSet { other.is_subset(self) } + /// Returns a reference to the first value in the set, if any. + /// This value is always the minimum of all values in the set. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut map = BTreeSet::new(); + /// assert_eq!(map.first(), None); + /// map.insert(1); + /// assert_eq!(map.first(), Some(&1)); + /// map.insert(2); + /// assert_eq!(map.first(), Some(&1)); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn first(&self) -> Option<&T> { + self.map.first_key_value().map(|(k, _)| k) + } + + /// Returns a reference to the last value in the set, if any. + /// This value is always the maximum of all values in the set. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut map = BTreeSet::new(); + /// assert_eq!(map.first(), None); + /// map.insert(1); + /// assert_eq!(map.last(), Some(&1)); + /// map.insert(2); + /// assert_eq!(map.last(), Some(&2)); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn last(&self) -> Option<&T> { + self.map.last_key_value().map(|(k, _)| k) + } + + /// Removes the first value from the set and returns it, if any. + /// The first value is always the minimum value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(1); + /// while let Some(n) = set.pop_first() { + /// assert_eq!(n, 1); + /// } + /// assert!(set.is_empty()); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn pop_first(&mut self) -> Option { + self.map.first_entry().map(|entry| entry.remove_entry().0) + } + + /// Removes the last value from the set and returns it, if any. + /// The last value is always the maximum value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(map_first_last)] + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(1); + /// while let Some(n) = set.pop_last() { + /// assert_eq!(n, 1); + /// } + /// assert!(set.is_empty()); + /// ``` + #[unstable(feature = "map_first_last", issue = "62924")] + pub fn pop_last(&mut self) -> Option { + self.map.last_entry().map(|entry| entry.remove_entry().0) + } + /// Adds a value to the set. /// /// If the set did not have this value present, `true` is returned. diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 702df25099..4a74a479e7 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -3,11 +3,11 @@ //! The `LinkedList` allows pushing and popping elements at either end //! in constant time. //! -//! Almost always it is better to use `Vec` or [`VecDeque`] instead of -//! [`LinkedList`]. In general, array-based containers are faster, -//! more memory efficient and make better use of CPU cache. +//! NOTE: It is almost always better to use [`Vec`] or [`VecDeque`] because +//! array-based containers are generally faster, +//! more memory efficient, and make better use of CPU cache. //! -//! [`LinkedList`]: ../linked_list/struct.LinkedList.html +//! [`Vec`]: ../../vec/struct.Vec.html //! [`VecDeque`]: ../vec_deque/struct.VecDeque.html #![stable(feature = "rust1", since = "1.0.0")] @@ -31,9 +31,9 @@ mod tests; /// The `LinkedList` allows pushing and popping elements at either end /// in constant time. /// -/// Almost always it is better to use `Vec` or `VecDeque` instead of -/// `LinkedList`. In general, array-based containers are faster, -/// more memory efficient and make better use of CPU cache. +/// NOTE: It is almost always better to use `Vec` or `VecDeque` because +/// array-based containers are generally faster, +/// more memory efficient, and make better use of CPU cache. #[stable(feature = "rust1", since = "1.0.0")] pub struct LinkedList { head: Option>>, @@ -90,7 +90,7 @@ impl Clone for Iter<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { // We do *not* exclusively own the entire list here, references to node's `element` - // have been handed out by the iterator! So be careful when using this; the methods + // have been handed out by the iterator! So be careful when using this; the methods // called must be aware that there can be aliasing pointers to `element`. list: &'a mut LinkedList, head: Option>>, @@ -275,6 +275,10 @@ impl LinkedList { /// let list: LinkedList = LinkedList::new(); /// ``` #[inline] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0"), + )] #[stable(feature = "rust1", since = "1.0.0")] pub const fn new() -> Self { LinkedList { @@ -808,7 +812,21 @@ impl LinkedList { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T> Drop for LinkedList { fn drop(&mut self) { - while let Some(_) = self.pop_front_node() {} + struct DropGuard<'a, T>(&'a mut LinkedList); + + impl<'a, T> Drop for DropGuard<'a, T> { + fn drop(&mut self) { + // Continue the same loop we do below. This only runs when a destructor has + // panicked. If another one panics this will abort. + while let Some(_) = self.0.pop_front_node() {} + } + } + + while let Some(node) = self.pop_front_node() { + let guard = DropGuard(self); + drop(node); + mem::forget(guard); + } } } diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs index 1001f6bba3..1b1d8eab39 100644 --- a/src/liballoc/collections/linked_list/tests.rs +++ b/src/liballoc/collections/linked_list/tests.rs @@ -177,23 +177,22 @@ fn test_insert_prev() { } check_links(&m); assert_eq!(m.len(), 3 + len * 2); - assert_eq!(m.into_iter().collect::>(), - [-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]); + assert_eq!(m.into_iter().collect::>(), [-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]); } #[test] #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg(not(miri))] // Miri does not support threads +#[cfg_attr(miri, ignore)] // Miri does not support threads fn test_send() { let n = list_from(&[1, 2, 3]); thread::spawn(move || { - check_links(&n); - let a: &[_] = &[&1, &2, &3]; - assert_eq!(a, &*n.iter().collect::>()); - }) - .join() - .ok() - .unwrap(); + check_links(&n); + let a: &[_] = &[&1, &2, &3]; + assert_eq!(a, &*n.iter().collect::>()); + }) + .join() + .ok() + .unwrap(); } #[test] diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 8f3dfabd88..913613653a 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -144,11 +144,23 @@ impl Clone for VecDeque { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T> Drop for VecDeque { fn drop(&mut self) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + let (front, back) = self.as_mut_slices(); unsafe { + let _back_dropper = Dropper(back); // use drop for [T] ptr::drop_in_place(front); - ptr::drop_in_place(back); } // RawVec handles deallocation } @@ -835,7 +847,8 @@ impl VecDeque { } } - /// Shortens the `VecDeque`, dropping excess elements from the back. + /// Shortens the `VecDeque`, keeping the first `len` elements and dropping + /// the rest. /// /// If `len` is greater than the `VecDeque`'s current length, this has no /// effect. @@ -855,8 +868,31 @@ impl VecDeque { /// ``` #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) { - for _ in len..self.len() { - self.pop_back(); + // Safe because: + // + // * Any slice passed to `drop_in_place` is valid; the second case has + // `len <= front.len()` and returning on `len > self.len()` ensures + // `begin <= back.len()` in the first case + // * The head of the VecDeque is moved before calling `drop_in_place`, + // so no value is dropped twice if `drop_in_place` panics + unsafe { + if len > self.len() { + return; + } + let num_dropped = self.len() - len; + let (front, back) = self.as_mut_slices(); + if len > front.len() { + let begin = len - front.len(); + let drop_back = back.get_unchecked_mut(begin..) as *mut _; + self.head = self.wrap_sub(self.head, num_dropped); + ptr::drop_in_place(drop_back); + } else { + let drop_back = back as *mut _; + let drop_front = front.get_unchecked_mut(len..) as *mut _; + self.head = self.wrap_sub(self.head, num_dropped); + ptr::drop_in_place(drop_front); + ptr::drop_in_place(drop_back); + } } } @@ -1117,7 +1153,7 @@ impl VecDeque { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn clear(&mut self) { - self.drain(..); + self.truncate(0); } /// Returns `true` if the `VecDeque` contains an element equal to the @@ -2785,7 +2821,22 @@ impl<'a, T> IntoIterator for &'a mut VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for VecDeque { fn extend>(&mut self, iter: T) { - iter.into_iter().for_each(move |elt| self.push_back(elt)); + // This function should be the moral equivalent of: + // + // for item in iter.into_iter() { + // self.push_back(item); + // } + let mut iter = iter.into_iter(); + while let Some(element) = iter.next() { + if self.len() == self.capacity() { + let (lower, _) = iter.size_hint(); + self.reserve(lower.saturating_add(1)); + } + + let head = self.head; + self.head = self.wrap_add(self.head, 1); + unsafe { self.buffer_write(head, element); } + } } } diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs index d578ee0dac..f2ce5b1d15 100644 --- a/src/liballoc/collections/vec_deque/tests.rs +++ b/src/liballoc/collections/vec_deque/tests.rs @@ -3,7 +3,7 @@ use super::*; use ::test; #[bench] -#[cfg(not(miri))] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // Miri does not support benchmarks fn bench_push_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -16,7 +16,7 @@ fn bench_push_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg(not(miri))] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // Miri does not support benchmarks fn bench_push_front_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -29,7 +29,7 @@ fn bench_push_front_100(b: &mut test::Bencher) { } #[bench] -#[cfg(not(miri))] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // Miri does not support benchmarks fn bench_pop_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::::with_capacity(101); @@ -43,7 +43,7 @@ fn bench_pop_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg(not(miri))] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // Miri does not support benchmarks fn bench_pop_front_100(b: &mut test::Bencher) { let mut deq = VecDeque::::with_capacity(101); @@ -66,11 +66,8 @@ fn test_swap_front_back_remove() { let final_len = usable_cap / 2; for len in 0..final_len { - let expected: VecDeque<_> = if back { - (0..len).collect() - } else { - (0..len).rev().collect() - }; + let expected: VecDeque<_> = + if back { (0..len).collect() } else { (0..len).rev().collect() }; for tail_pos in 0..usable_cap { tester.tail = tail_pos; tester.head = tail_pos; @@ -111,7 +108,6 @@ fn test_insert() { // this test isn't covering what it wants to let cap = tester.capacity(); - // len is the length *after* insertion for len in 1..cap { // 0, 1, 2, .., len - 1 @@ -198,9 +194,7 @@ fn test_drain() { assert!(tester.head < tester.cap()); // We should see the correct values in the VecDeque - let expected: VecDeque<_> = (0..drain_start) - .chain(drain_end..len) - .collect(); + let expected: VecDeque<_> = (0..drain_start).chain(drain_end..len).collect(); assert_eq!(expected, tester); } } @@ -384,6 +378,41 @@ fn test_clone_from() { } } +#[test] +fn test_vec_deque_truncate_drop() { + static mut DROPS: u32 = 0; + #[derive(Clone)] + struct Elem(i32); + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; + for push_front in 0..=v.len() { + let v = v.clone(); + let mut tester = VecDeque::with_capacity(5); + for (index, elem) in v.into_iter().enumerate() { + if index < push_front { + tester.push_front(elem); + } else { + tester.push_back(elem); + } + } + assert_eq!(unsafe { DROPS }, 0); + tester.truncate(3); + assert_eq!(unsafe { DROPS }, 2); + tester.truncate(0); + assert_eq!(unsafe { DROPS }, 5); + unsafe { + DROPS = 0; + } + } +} + #[test] fn issue_53529() { use crate::boxed::Box; diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index cbfc55233a..18ebae3330 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -516,24 +516,24 @@ #[unstable(feature = "fmt_internals", issue = "0")] pub use core::fmt::rt; +#[stable(feature = "fmt_flags_align", since = "1.28.0")] +pub use core::fmt::Alignment; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{Formatter, Result, Write}; +pub use core::fmt::Error; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::fmt::{write, ArgumentV1, Arguments}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{Binary, Octal}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{Debug, Display}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{LowerHex, Pointer, UpperHex}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{LowerExp, UpperExp}; +pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::Error; +pub use core::fmt::{Formatter, Result, Write}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{write, ArgumentV1, Arguments}; +pub use core::fmt::{LowerExp, UpperExp}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; -#[stable(feature = "fmt_flags_align", since = "1.28.0")] -pub use core::fmt::{Alignment}; +pub use core::fmt::{LowerHex, Pointer, UpperHex}; use crate::string; @@ -568,8 +568,6 @@ use crate::string; pub fn format(args: Arguments<'_>) -> string::String { let capacity = args.estimated_capacity(); let mut output = string::String::with_capacity(capacity); - output - .write_fmt(args) - .expect("a formatting trait implementation returned an error"); + output.write_fmt(args).expect("a formatting trait implementation returned an error"); output } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 94379afc2b..d828e374a7 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -116,8 +116,8 @@ #![feature(unsize)] #![feature(unsized_locals)] #![feature(allocator_internals)] -#![feature(on_unimplemented)] -#![feature(rustc_const_unstable)] +#![cfg_attr(bootstrap, feature(on_unimplemented))] +#![cfg_attr(bootstrap, feature(rustc_const_unstable))] #![feature(slice_partition_dedup)] #![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 2f2cdc39c6..422d3486f9 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -98,5 +98,8 @@ macro_rules! vec { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! format { - ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*))) + ($($arg:tt)*) => {{ + let res = $crate::fmt::format($crate::__export::format_args!($($arg)*)); + res + }} } diff --git a/src/liballoc/prelude/v1.rs b/src/liballoc/prelude/v1.rs index 3cb285bf04..6a53b4ca1f 100644 --- a/src/liballoc/prelude/v1.rs +++ b/src/liballoc/prelude/v1.rs @@ -4,7 +4,11 @@ #![unstable(feature = "alloc_prelude", issue = "58935")] -#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::borrow::ToOwned; -#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::boxed::Box; -#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::string::{String, ToString}; -#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::vec::Vec; +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::borrow::ToOwned; +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::boxed::Box; +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::string::{String, ToString}; +#[unstable(feature = "alloc_prelude", issue = "58935")] +pub use crate::vec::Vec; diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index d35b62fc1e..b214cef301 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -16,7 +16,9 @@ fn allocator_param() { // A dumb allocator that consumes a fixed amount of fuel // before allocation attempts start failing. - struct BoundedAlloc { fuel: usize } + struct BoundedAlloc { + fuel: usize, + } unsafe impl Alloc for BoundedAlloc { unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { let size = layout.size(); @@ -24,7 +26,10 @@ fn allocator_param() { return Err(AllocErr); } match Global.alloc(layout) { - ok @ Ok(_) => { self.fuel -= size; ok } + ok @ Ok(_) => { + self.fuel -= size; + ok + } err @ Err(_) => err, } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index f1c4c32e11..42a278de98 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -280,7 +280,7 @@ struct RcBox { #[stable(feature = "rust1", since = "1.0.0")] pub struct Rc { ptr: NonNull>, - phantom: PhantomData, + phantom: PhantomData>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -361,6 +361,35 @@ impl Rc { } } + /// Constructs a new `Rc` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and + /// incorrect usage of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// use std::rc::Rc; + /// + /// let zero = Rc::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed() -> Rc> { + unsafe { + let mut uninit = Self::new_uninit(); + ptr::write_bytes::(Rc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1); + uninit + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -897,7 +926,7 @@ impl Rc { // reference (see #54908). let layout = Layout::new::>() .extend(value_layout).unwrap().0 - .pad_to_align().unwrap(); + .pad_to_align(); // Allocate for the layout. let mem = Global.alloc(layout) @@ -1619,10 +1648,8 @@ impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// - /// It is up to the caller to ensure that the object is still alive when accessing it through - /// the pointer. - /// - /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// The pointer is valid only if there are some strong references. The pointer may be dangling + /// or even [`null`] otherwise. /// /// # Examples /// @@ -1702,14 +1729,18 @@ impl Weak { /// This can be used to safely get a strong reference (by calling [`upgrade`] /// later) or to deallocate the weak count by dropping the `Weak`. /// - /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is - /// returned. + /// It takes ownership of one weak count (with the exception of pointers created by [`new`], + /// as these don't have any corresponding weak count). /// /// # Safety /// - /// The pointer must represent one valid weak count. In other words, it must point to `T` which - /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached - /// 0. It is allowed for the strong count to be 0. + /// The pointer must have originated from the [`into_raw`] (or [`as_raw`], provided there was + /// a corresponding [`forget`] on the `Weak`) and must still own its potential weak reference + /// count. + /// + /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count + /// must be non-zero or the pointer must have originated from a dangling `Weak` (one created + /// by [`new`]). /// /// # Examples /// @@ -1734,11 +1765,13 @@ impl Weak { /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); /// ``` /// - /// [`null`]: ../../std/ptr/fn.null.html /// [`into_raw`]: struct.Weak.html#method.into_raw /// [`upgrade`]: struct.Weak.html#method.upgrade /// [`Rc`]: struct.Rc.html /// [`Weak`]: struct.Weak.html + /// [`as_raw`]: struct.Weak.html#method.as_raw + /// [`new`]: struct.Weak.html#method.new + /// [`forget`]: ../../std/mem/fn.forget.html #[unstable(feature = "weak_into_raw", issue = "60728")] pub unsafe fn from_raw(ptr: *const T) -> Self { if ptr.is_null() { @@ -1803,7 +1836,7 @@ impl Weak { /// If `self` was created using [`Weak::new`], this will return 0. /// /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] + #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { if let Some(inner) = self.inner() { inner.strong() @@ -1814,20 +1847,16 @@ impl Weak { /// Gets the number of `Weak` pointers pointing to this allocation. /// - /// If `self` was created using [`Weak::new`], this will return `None`. If - /// not, the returned value is at least 1, since `self` still points to the - /// allocation. - /// - /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] - pub fn weak_count(&self) -> Option { + /// If no strong pointers remain, this will return zero. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { self.inner().map(|inner| { if inner.strong() > 0 { inner.weak() - 1 // subtract the implicit weak ptr } else { - inner.weak() + 0 } - }) + }).unwrap_or(0) } /// Returns `None` when the pointer is dangling and there is no allocated `RcBox` diff --git a/src/liballoc/rc/tests.rs b/src/liballoc/rc/tests.rs index 6fd3f90935..bf5c85a5c5 100644 --- a/src/liballoc/rc/tests.rs +++ b/src/liballoc/rc/tests.rs @@ -114,28 +114,28 @@ fn test_weak_count() { #[test] fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::::new()), None); + assert_eq!(Weak::weak_count(&Weak::::new()), 0); assert_eq!(Weak::strong_count(&Weak::::new()), 0); let a = Rc::new(0); let w = Rc::downgrade(&a); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(1)); + assert_eq!(Weak::weak_count(&w), 1); let w2 = w.clone(); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(2)); + assert_eq!(Weak::weak_count(&w), 2); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(2)); + assert_eq!(Weak::weak_count(&w2), 2); drop(w); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); let a2 = a.clone(); assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); drop(a2); drop(a); assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 0); drop(w2); } diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 08243ef7c5..2f6d10c027 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -82,7 +82,6 @@ //! [`.chunks`]: ../../std/primitive.slice.html#method.chunks //! [`.windows`]: ../../std/primitive.slice.html#method.windows #![stable(feature = "rust1", since = "1.0.0")] - // Many of the usings in this module are only used in the test configuration. // It's cleaner to just turn off the unused_imports warning than to fix them. #![cfg_attr(test, allow(unused_imports, dead_code))] @@ -91,32 +90,32 @@ use core::borrow::{Borrow, BorrowMut}; use core::cmp::Ordering::{self, Less}; use core::mem::{self, size_of}; use core::ptr; -use core::{u8, u16, u32}; +use core::{u16, u32, u8}; use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; +#[stable(feature = "slice_get_slice", since = "1.28.0")] +pub use core::slice::SliceIndex; +#[stable(feature = "from_ref", since = "1.28.0")] +pub use core::slice::{from_mut, from_ref}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::slice::{Chunks, Windows}; +pub use core::slice::{from_raw_parts, from_raw_parts_mut}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::slice::{Iter, IterMut}; +pub use core::slice::{Chunks, Windows}; +#[stable(feature = "chunks_exact", since = "1.31.0")] +pub use core::slice::{ChunksExact, ChunksExactMut}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::slice::{SplitMut, ChunksMut, Split}; +pub use core::slice::{ChunksMut, Split, SplitMut}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; +pub use core::slice::{Iter, IterMut}; +#[stable(feature = "rchunks", since = "1.31.0")] +pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; #[stable(feature = "slice_rsplit", since = "1.27.0")] pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::slice::{from_raw_parts, from_raw_parts_mut}; -#[stable(feature = "from_ref", since = "1.28.0")] -pub use core::slice::{from_ref, from_mut}; -#[stable(feature = "slice_get_slice", since = "1.28.0")] -pub use core::slice::SliceIndex; -#[stable(feature = "chunks_exact", since = "1.31.0")] -pub use core::slice::{ChunksExact, ChunksExactMut}; -#[stable(feature = "rchunks", since = "1.31.0")] -pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut}; +pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods @@ -138,9 +137,9 @@ pub use hack::to_vec; // `test_permutations` test mod hack { use crate::boxed::Box; - use crate::vec::Vec; #[cfg(test)] use crate::string::ToString; + use crate::vec::Vec; pub fn into_vec(b: Box<[T]>) -> Vec { unsafe { @@ -153,7 +152,8 @@ mod hack { #[inline] pub fn to_vec(s: &[T]) -> Vec - where T: Clone + where + T: Clone, { let mut vector = Vec::with_capacity(s.len()); vector.extend_from_slice(s); @@ -193,7 +193,8 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort(&mut self) - where T: Ord + where + T: Ord, { merge_sort(self, |a, b| a.lt(b)); } @@ -246,7 +247,8 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sort_by(&mut self, mut compare: F) - where F: FnMut(&T, &T) -> Ordering + where + F: FnMut(&T, &T) -> Ordering, { merge_sort(self, |a, b| compare(a, b) == Less); } @@ -285,7 +287,9 @@ impl [T] { #[stable(feature = "slice_sort_by_key", since = "1.7.0")] #[inline] pub fn sort_by_key(&mut self, mut f: F) - where F: FnMut(&T) -> K, K: Ord + where + F: FnMut(&T) -> K, + K: Ord, { merge_sort(self, |a, b| f(a).lt(&f(b))); } @@ -325,11 +329,13 @@ impl [T] { #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")] #[inline] pub fn sort_by_cached_key(&mut self, f: F) - where F: FnMut(&T) -> K, K: Ord + where + F: FnMut(&T) -> K, + K: Ord, { // Helper macro for indexing our vector by the smallest possible type, to reduce allocation. macro_rules! sort_by_key { - ($t:ty, $slice:ident, $f:ident) => ({ + ($t:ty, $slice:ident, $f:ident) => {{ let mut indices: Vec<_> = $slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect(); // The elements of `indices` are unique, as they are indexed, so any sort will be @@ -344,19 +350,27 @@ impl [T] { indices[i].1 = index; $slice.swap(i, index as usize); } - }) + }}; } - let sz_u8 = mem::size_of::<(K, u8)>(); - let sz_u16 = mem::size_of::<(K, u16)>(); - let sz_u32 = mem::size_of::<(K, u32)>(); + let sz_u8 = mem::size_of::<(K, u8)>(); + let sz_u16 = mem::size_of::<(K, u16)>(); + let sz_u32 = mem::size_of::<(K, u32)>(); let sz_usize = mem::size_of::<(K, usize)>(); let len = self.len(); - if len < 2 { return } - if sz_u8 < sz_u16 && len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } - if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } - if sz_u32 < sz_usize && len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } + if len < 2 { + return; + } + if sz_u8 < sz_u16 && len <= (u8::MAX as usize) { + return sort_by_key!(u8, self, f); + } + if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { + return sort_by_key!(u16, self, f); + } + if sz_u32 < sz_usize && len <= (u32::MAX as usize) { + return sort_by_key!(u32, self, f); + } sort_by_key!(usize, self, f) } @@ -373,7 +387,8 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_vec(&self) -> Vec - where T: Clone + where + T: Clone, { // N.B., see the `hack` module in this file for more details. hack::to_vec(self) @@ -421,7 +436,10 @@ impl [T] { /// b"0123456789abcdef".repeat(usize::max_value()); /// ``` #[stable(feature = "repeat_generic_slice", since = "1.40.0")] - pub fn repeat(&self, n: usize) -> Vec where T: Copy { + pub fn repeat(&self, n: usize) -> Vec + where + T: Copy, + { if n == 0 { return Vec::new(); } @@ -486,7 +504,8 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn concat(&self) -> >::Output - where Self: Concat + where + Self: Concat, { Concat::concat(self) } @@ -503,7 +522,8 @@ impl [T] { /// ``` #[stable(feature = "rename_connect_to_join", since = "1.3.0")] pub fn join(&self, sep: Separator) -> >::Output - where Self: Join + where + Self: Join, { Join::join(self, sep) } @@ -521,11 +541,11 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")] pub fn connect(&self, sep: Separator) -> >::Output - where Self: Join + where + Self: Join, { Join::join(self, sep) } - } #[lang = "slice_u8_alloc"] @@ -668,8 +688,8 @@ impl> Join<&[T]> for [V] { Some(first) => first, None => return vec![], }; - let size = slice.iter().map(|v| v.borrow().len()).sum::() + - sep.len() * (slice.len() - 1); + let size = + slice.iter().map(|v| v.borrow().len()).sum::() + sep.len() * (slice.len() - 1); let mut result = Vec::with_capacity(size); result.extend_from_slice(first.borrow()); @@ -734,7 +754,8 @@ impl ToOwned for [T] { /// /// This is the integral subroutine of insertion sort. fn insert_head(v: &mut [T], is_less: &mut F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { if v.len() >= 2 && is_less(&v[1], &v[0]) { unsafe { @@ -767,10 +788,7 @@ fn insert_head(v: &mut [T], is_less: &mut F) // If `is_less` panics at any point during the process, `hole` will get dropped and // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it // initially held exactly once. - let mut hole = InsertionHole { - src: &mut *tmp, - dest: &mut v[1], - }; + let mut hole = InsertionHole { src: &mut *tmp, dest: &mut v[1] }; ptr::copy_nonoverlapping(&v[1], &mut v[0], 1); for i in 2..v.len() { @@ -792,7 +810,9 @@ fn insert_head(v: &mut [T], is_less: &mut F) impl Drop for InsertionHole { fn drop(&mut self) { - unsafe { ptr::copy_nonoverlapping(self.src, self.dest, 1); } + unsafe { + ptr::copy_nonoverlapping(self.src, self.dest, 1); + } } } } @@ -805,7 +825,8 @@ fn insert_head(v: &mut [T], is_less: &mut F) /// The two slices must be non-empty and `mid` must be in bounds. Buffer `buf` must be long enough /// to hold a copy of the shorter slice. Also, `T` must not be a zero-sized type. unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { let len = v.len(); let v = v.as_mut_ptr(); @@ -834,11 +855,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) if mid <= len - mid { // The left run is shorter. ptr::copy_nonoverlapping(v, buf, mid); - hole = MergeHole { - start: buf, - end: buf.add(mid), - dest: v, - }; + hole = MergeHole { start: buf, end: buf.add(mid), dest: v }; // Initially, these pointers point to the beginnings of their arrays. let left = &mut hole.start; @@ -858,11 +875,7 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) } else { // The right run is shorter. ptr::copy_nonoverlapping(v_mid, buf, len - mid); - hole = MergeHole { - start: buf, - end: buf.add(len - mid), - dest: v_mid, - }; + hole = MergeHole { start: buf, end: buf.add(len - mid), dest: v_mid }; // Initially, these pointers point past the ends of their arrays. let left = &mut hole.dest; @@ -905,7 +918,9 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) fn drop(&mut self) { // `T` is not a zero-sized type, so it's okay to divide by its size. let len = (self.end as usize - self.start as usize) / mem::size_of::(); - unsafe { ptr::copy_nonoverlapping(self.start, self.dest, len); } + unsafe { + ptr::copy_nonoverlapping(self.start, self.dest, len); + } } } } @@ -923,7 +938,8 @@ unsafe fn merge(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F) /// /// The invariants ensure that the total running time is `O(n log n)` worst-case. fn merge_sort(v: &mut [T], mut is_less: F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // Slices of up to this length get sorted using insertion sort. const MAX_INSERTION: usize = 20; @@ -940,7 +956,7 @@ fn merge_sort(v: &mut [T], mut is_less: F) // Short arrays get sorted in-place via insertion sort to avoid allocations. if len <= MAX_INSERTION { if len >= 2 { - for i in (0..len-1).rev() { + for i in (0..len - 1).rev() { insert_head(&mut v[i..], &mut is_less); } } @@ -966,14 +982,13 @@ fn merge_sort(v: &mut [T], mut is_less: F) start -= 1; unsafe { if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) { - while start > 0 && is_less(v.get_unchecked(start), - v.get_unchecked(start - 1)) { + while start > 0 && is_less(v.get_unchecked(start), v.get_unchecked(start - 1)) { start -= 1; } v[start..end].reverse(); } else { - while start > 0 && !is_less(v.get_unchecked(start), - v.get_unchecked(start - 1)) { + while start > 0 && !is_less(v.get_unchecked(start), v.get_unchecked(start - 1)) + { start -= 1; } } @@ -988,10 +1003,7 @@ fn merge_sort(v: &mut [T], mut is_less: F) } // Push this run onto the stack. - runs.push(Run { - start, - len: end - start, - }); + runs.push(Run { start, len: end - start }); end = start; // Merge some pairs of adjacent runs to satisfy the invariants. @@ -999,13 +1011,14 @@ fn merge_sort(v: &mut [T], mut is_less: F) let left = runs[r + 1]; let right = runs[r]; unsafe { - merge(&mut v[left.start .. right.start + right.len], left.len, buf.as_mut_ptr(), - &mut is_less); + merge( + &mut v[left.start..right.start + right.len], + left.len, + buf.as_mut_ptr(), + &mut is_less, + ); } - runs[r] = Run { - start: left.start, - len: left.len + right.len, - }; + runs[r] = Run { start: left.start, len: left.len + right.len }; runs.remove(r + 1); } } @@ -1030,15 +1043,13 @@ fn merge_sort(v: &mut [T], mut is_less: F) #[inline] fn collapse(runs: &[Run]) -> Option { let n = runs.len(); - if n >= 2 && (runs[n - 1].start == 0 || - runs[n - 2].len <= runs[n - 1].len || - (n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len) || - (n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len)) { - if n >= 3 && runs[n - 3].len < runs[n - 1].len { - Some(n - 3) - } else { - Some(n - 2) - } + if n >= 2 + && (runs[n - 1].start == 0 + || runs[n - 2].len <= runs[n - 1].len + || (n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len) + || (n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len)) + { + if n >= 3 && runs[n - 3].len < runs[n - 1].len { Some(n - 3) } else { Some(n - 2) } } else { None } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index d9927c642b..bf9bbba475 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -367,6 +367,10 @@ impl String { /// let s = String::new(); /// ``` #[inline] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_string_new", since = "1.32.0"), + )] #[stable(feature = "rust1", since = "1.0.0")] pub const fn new() -> String { String { vec: Vec::new() } @@ -687,7 +691,7 @@ impl String { /// checked: /// /// * The memory at `ptr` needs to have been previously allocated by the - /// same allocator the standard library uses. + /// same allocator the standard library uses, with a required alignment of exactly 1. /// * `length` needs to be less than or equal to `capacity`. /// * `capacity` needs to be the correct value. /// @@ -1402,7 +1406,9 @@ impl String { &mut self.vec } - /// Returns the length of this `String`, in bytes. + /// Returns the length of this `String`, in bytes, not [`char`]s or + /// graphemes. In other words, it may not be what a human considers the + /// length of the string. /// /// # Examples /// @@ -1410,8 +1416,11 @@ impl String { /// /// ``` /// let a = String::from("foo"); - /// /// assert_eq!(a.len(), 3); + /// + /// let fancy_f = String::from("ƒoo"); + /// assert_eq!(fancy_f.len(), 4); + /// assert_eq!(fancy_f.chars().count(), 3); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 80d6c6e0d4..a99564c0da 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -12,7 +12,7 @@ use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::borrow; use core::fmt; -use core::cmp::{self, Ordering}; +use core::cmp::Ordering; use core::iter; use core::intrinsics::abort; use core::mem::{self, align_of, align_of_val, size_of_val}; @@ -195,7 +195,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; #[stable(feature = "rust1", since = "1.0.0")] pub struct Arc { ptr: NonNull>, - phantom: PhantomData, + phantom: PhantomData>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -341,6 +341,35 @@ impl Arc { } } + /// Constructs a new `Arc` with uninitialized contents, with the memory + /// being filled with `0` bytes. + /// + /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// use std::sync::Arc; + /// + /// let zero = Arc::::new_zeroed(); + /// let zero = unsafe { zero.assume_init() }; + /// + /// assert_eq!(*zero, 0) + /// ``` + /// + /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_zeroed() -> Arc> { + unsafe { + let mut uninit = Self::new_uninit(); + ptr::write_bytes::(Arc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1); + uninit + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -751,7 +780,7 @@ impl Arc { // reference (see #54908). let layout = Layout::new::>() .extend(value_layout).unwrap().0 - .pad_to_align().unwrap(); + .pad_to_align(); let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); @@ -1295,10 +1324,8 @@ impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// - /// It is up to the caller to ensure that the object is still alive when accessing it through - /// the pointer. - /// - /// The pointer may be [`null`] or be dangling in case the object has already been destroyed. + /// The pointer is valid only if there are some strong references. The pointer may be dangling + /// or even [`null`] otherwise. /// /// # Examples /// @@ -1379,14 +1406,18 @@ impl Weak { /// This can be used to safely get a strong reference (by calling [`upgrade`] /// later) or to deallocate the weak count by dropping the `Weak`. /// - /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is - /// returned. + /// It takes ownership of one weak count (with the exception of pointers created by [`new`], + /// as these don't have any corresponding weak count). /// /// # Safety /// - /// The pointer must represent one valid weak count. In other words, it must point to `T` which - /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached - /// 0. It is allowed for the strong count to be 0. + /// The pointer must have originated from the [`into_raw`] (or [`as_raw'], provided there was + /// a corresponding [`forget`] on the `Weak`) and must still own its potential weak reference + /// count. + /// + /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count + /// must be non-zero or the pointer must have originated from a dangling `Weak` (one created + /// by [`new`]). /// /// # Examples /// @@ -1411,11 +1442,13 @@ impl Weak { /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); /// ``` /// - /// [`null`]: ../../std/ptr/fn.null.html + /// [`as_raw`]: struct.Weak.html#method.as_raw + /// [`new`]: struct.Weak.html#method.new /// [`into_raw`]: struct.Weak.html#method.into_raw /// [`upgrade`]: struct.Weak.html#method.upgrade /// [`Weak`]: struct.Weak.html /// [`Arc`]: struct.Arc.html + /// [`forget`]: ../../std/mem/fn.forget.html #[unstable(feature = "weak_into_raw", issue = "60728")] pub unsafe fn from_raw(ptr: *const T) -> Self { if ptr.is_null() { @@ -1496,7 +1529,7 @@ impl Weak { /// If `self` was created using [`Weak::new`], this will return 0. /// /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] + #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { if let Some(inner) = self.inner() { inner.strong.load(SeqCst) @@ -1508,9 +1541,8 @@ impl Weak { /// Gets an approximation of the number of `Weak` pointers pointing to this /// allocation. /// - /// If `self` was created using [`Weak::new`], this will return 0. If not, - /// the returned value is at least 1, since `self` still points to the - /// allocation. + /// If `self` was created using [`Weak::new`], or if there are no remaining + /// strong pointers, this will return 0. /// /// # Accuracy /// @@ -1519,31 +1551,22 @@ impl Weak { /// `Weak`s pointing to the same allocation. /// /// [`Weak::new`]: #method.new - #[unstable(feature = "weak_counts", issue = "57977")] - pub fn weak_count(&self) -> Option { - // Due to the implicit weak pointer added when any strong pointers are - // around, we cannot implement `weak_count` correctly since it - // necessarily requires accessing the strong count and weak count in an - // unsynchronized fashion. So this version is a bit racy. + #[stable(feature = "weak_counts", since = "1.41.0")] + pub fn weak_count(&self) -> usize { self.inner().map(|inner| { - let strong = inner.strong.load(SeqCst); let weak = inner.weak.load(SeqCst); + let strong = inner.strong.load(SeqCst); if strong == 0 { - // If the last `Arc` has *just* been dropped, it might not yet - // have removed the implicit weak count, so the value we get - // here might be 1 too high. - weak + 0 } else { - // As long as there's still at least 1 `Arc` around, subtract - // the implicit weak pointer. - // Note that the last `Arc` might get dropped between the 2 - // loads we do above, removing the implicit weak pointer. This - // means that the value might be 1 too low here. In order to not - // return 0 here (which would happen if we're the only weak - // pointer), we guard against that specifically. - cmp::max(1, weak - 1) + // Since we observed that there was at least one strong pointer + // after reading the weak count, we know that the implicit weak + // reference (present whenever any strong references are alive) + // was still around when we observed the weak count, and can + // therefore safely subtract it. + weak - 1 } - }) + }).unwrap_or(0) } /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs index 9220f5e033..8f516129cd 100644 --- a/src/liballoc/sync/tests.rs +++ b/src/liballoc/sync/tests.rs @@ -29,7 +29,7 @@ impl Drop for Canary { #[test] #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg(not(miri))] // Miri does not support threads +#[cfg_attr(miri, ignore)] // Miri does not support threads fn manually_share_arc() { let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let arc_v = Arc::new(v); @@ -62,28 +62,28 @@ fn test_arc_get_mut() { #[test] fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::::new()), None); + assert_eq!(Weak::weak_count(&Weak::::new()), 0); assert_eq!(Weak::strong_count(&Weak::::new()), 0); let a = Arc::new(0); let w = Arc::downgrade(&a); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(1)); + assert_eq!(Weak::weak_count(&w), 1); let w2 = w.clone(); assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), Some(2)); + assert_eq!(Weak::weak_count(&w), 2); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(2)); + assert_eq!(Weak::weak_count(&w2), 2); drop(w); assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); let a2 = a.clone(); assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 1); drop(a2); drop(a); assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), Some(1)); + assert_eq!(Weak::weak_count(&w2), 0); drop(w2); } @@ -334,7 +334,7 @@ fn test_ptr_eq() { #[test] #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg(not(miri))] // Miri does not support threads +#[cfg_attr(miri, ignore)] // Miri does not support threads fn test_weak_count_locked() { let mut a = Arc::new(atomic::AtomicBool::new(false)); let a2 = a.clone(); diff --git a/src/liballoc/tests.rs b/src/liballoc/tests.rs index ed46ba8a1b..1b6e0bb291 100644 --- a/src/liballoc/tests.rs +++ b/src/liballoc/tests.rs @@ -1,12 +1,12 @@ //! Test for `boxed` mod. use core::any::Any; -use core::convert::TryInto; -use core::ops::Deref; -use core::result::Result::{Err, Ok}; use core::clone::Clone; +use core::convert::TryInto; use core::f64; use core::i64; +use core::ops::Deref; +use core::result::Result::{Err, Ok}; use std::boxed::Box; diff --git a/src/liballoc/tests/arc.rs b/src/liballoc/tests/arc.rs index cf2ad2a8e6..2fbb59b041 100644 --- a/src/liballoc/tests/arc.rs +++ b/src/liballoc/tests/arc.rs @@ -1,9 +1,9 @@ use std::any::Any; -use std::sync::{Arc, Weak}; use std::cell::RefCell; use std::cmp::PartialEq; use std::iter::TrustedLen; use std::mem; +use std::sync::{Arc, Weak}; #[test] fn uninhabited() { @@ -12,7 +12,7 @@ fn uninhabited() { a = a.clone(); assert!(a.upgrade().is_none()); - let mut a: Weak = a; // Unsizing + let mut a: Weak = a; // Unsizing a = a.clone(); assert!(a.upgrade().is_none()); } @@ -20,8 +20,8 @@ fn uninhabited() { #[test] fn slice() { let a: Arc<[u32; 3]> = Arc::new([3, 2, 1]); - let a: Arc<[u32]> = a; // Unsizing - let b: Arc<[u32]> = Arc::from(&[3, 2, 1][..]); // Conversion + let a: Arc<[u32]> = a; // Unsizing + let b: Arc<[u32]> = Arc::from(&[3, 2, 1][..]); // Conversion assert_eq!(a, b); // Exercise is_dangling() with a DST @@ -33,7 +33,7 @@ fn slice() { #[test] fn trait_object() { let a: Arc = Arc::new(4); - let a: Arc = a; // Unsizing + let a: Arc = a; // Unsizing // Exercise is_dangling() with a DST let mut a = Arc::downgrade(&a); @@ -43,7 +43,7 @@ fn trait_object() { let mut b = Weak::::new(); b = b.clone(); assert!(b.upgrade().is_none()); - let mut b: Weak = b; // Unsizing + let mut b: Weak = b; // Unsizing b = b.clone(); assert!(b.upgrade().is_none()); } @@ -57,7 +57,7 @@ fn float_nan_ne() { #[test] fn partial_eq() { - struct TestPEq (RefCell); + struct TestPEq(RefCell); impl PartialEq for TestPEq { fn eq(&self, other: &TestPEq) -> bool { *self.0.borrow_mut() += 1; @@ -74,7 +74,7 @@ fn partial_eq() { #[test] fn eq() { #[derive(Eq)] - struct TestEq (RefCell); + struct TestEq(RefCell); impl PartialEq for TestEq { fn eq(&self, other: &TestEq) -> bool { *self.0.borrow_mut() += 1; @@ -160,13 +160,10 @@ fn shared_from_iter_trustedlen_normal() { fn shared_from_iter_trustedlen_panic() { // Exercise the `TrustedLen` implementation when `size_hint()` matches // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. - let iter = (0..SHARED_ITER_MAX) - .map(|val| { - match val { - 98 => panic!("I've almost got 99 problems."), - _ => Box::new(val), - } - }); + let iter = (0..SHARED_ITER_MAX).map(|val| match val { + 98 => panic!("I've almost got 99 problems."), + _ => Box::new(val), + }); assert_trusted_len(&iter); let _ = iter.collect::>(); @@ -193,16 +190,8 @@ fn shared_from_iter_trustedlen_no_fuse() { } } - let vec = vec![ - Some(Box::new(42)), - Some(Box::new(24)), - None, - Some(Box::new(12)), - ]; + let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))]; let iter = Iter(vec.into_iter()); assert_trusted_len(&iter); - assert_eq!( - &[Box::new(42), Box::new(24)], - &*iter.collect::>() - ); + assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::>()); } diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index a44cf1eaf6..a896a1064d 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -347,7 +347,7 @@ fn assert_covariance() { // Destructors must be called exactly once per element. // FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics +#[cfg(not(target_os = "emscripten"))] fn panic_safe() { use std::cmp; use std::panic::{self, AssertUnwindSafe}; @@ -376,7 +376,10 @@ fn panic_safe() { } let mut rng = thread_rng(); const DATASZ: usize = 32; + #[cfg(not(miri))] // Miri is too slow const NTEST: usize = 10; + #[cfg(miri)] + const NTEST: usize = 1; // don't use 0 in the data -- we want to catch the zeroed-out case. let data = (1..=DATASZ).collect::>(); diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs index bc3d53bf30..66782ecbeb 100644 --- a/src/liballoc/tests/boxed.rs +++ b/src/liballoc/tests/boxed.rs @@ -1,5 +1,5 @@ -use std::ptr::NonNull; use std::mem::MaybeUninit; +use std::ptr::NonNull; #[test] fn unitialized_zero_size_box() { diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 266a0d055d..27843aeaeb 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -58,15 +58,35 @@ fn test_basic_large() { fn test_basic_small() { let mut map = BTreeMap::new(); assert_eq!(map.remove(&1), None); + assert_eq!(map.len(), 0); + assert_eq!(map.first_key_value(), None); + assert_eq!(map.last_key_value(), None); assert_eq!(map.get(&1), None); assert_eq!(map.insert(1, 1), None); + assert_eq!(map.len(), 1); assert_eq!(map.get(&1), Some(&1)); + assert_eq!(map.first_key_value(), Some((&1, &1))); + assert_eq!(map.last_key_value(), Some((&1, &1))); assert_eq!(map.insert(1, 2), Some(1)); + assert_eq!(map.len(), 1); assert_eq!(map.get(&1), Some(&2)); + assert_eq!(map.first_key_value(), Some((&1, &2))); + assert_eq!(map.last_key_value(), Some((&1, &2))); assert_eq!(map.insert(2, 4), None); + assert_eq!(map.len(), 2); assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.first_key_value(), Some((&1, &2))); + assert_eq!(map.last_key_value(), Some((&2, &4))); assert_eq!(map.remove(&1), Some(2)); + assert_eq!(map.len(), 1); + assert_eq!(map.get(&1), None); + assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.first_key_value(), Some((&2, &4))); + assert_eq!(map.last_key_value(), Some((&2, &4))); assert_eq!(map.remove(&2), Some(4)); + assert_eq!(map.len(), 0); + assert_eq!(map.first_key_value(), None); + assert_eq!(map.last_key_value(), None); assert_eq!(map.remove(&1), None); } @@ -605,6 +625,31 @@ fn test_vacant_entry_key() { assert_eq!(a[key], value); } +#[test] +fn test_first_last_entry() { + let mut a = BTreeMap::new(); + assert!(a.first_entry().is_none()); + assert!(a.last_entry().is_none()); + a.insert(1, 42); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &1); + a.insert(2, 24); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &2); + a.insert(0, 6); + assert_eq!(a.first_entry().unwrap().key(), &0); + assert_eq!(a.last_entry().unwrap().key(), &2); + let (k1, v1) = a.first_entry().unwrap().remove_entry(); + assert_eq!(k1, 0); + assert_eq!(v1, 6); + let (k2, v2) = a.last_entry().unwrap().remove_entry(); + assert_eq!(k2, 2); + assert_eq!(v2, 24); + assert_eq!(a.first_entry().unwrap().key(), &1); + assert_eq!(a.last_entry().unwrap().key(), &1); +} + + macro_rules! create_append_test { ($name:ident, $len:expr) => { #[test] diff --git a/src/liballoc/tests/btree/mod.rs b/src/liballoc/tests/btree/mod.rs index 4c704d0f8c..1d08ae13e0 100644 --- a/src/liballoc/tests/btree/mod.rs +++ b/src/liballoc/tests/btree/mod.rs @@ -11,12 +11,7 @@ struct DeterministicRng { impl DeterministicRng { fn new() -> Self { - DeterministicRng { - x: 0x193a6754, - y: 0xa8a7d469, - z: 0x97830e05, - w: 0x113ba7bb, - } + DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } } fn next(&mut self) -> u32 { diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index e4883abc8b..13cd262802 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -470,6 +470,34 @@ fn test_append() { assert_eq!(a.contains(&5), true); } +#[test] +fn test_first_last() { + let mut a = BTreeSet::new(); + assert_eq!(a.first(), None); + assert_eq!(a.last(), None); + a.insert(1); + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&1)); + a.insert(2); + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&2)); + a.insert(3); + assert_eq!(a.first(), Some(&1)); + assert_eq!(a.last(), Some(&3)); + + assert_eq!(a.len(), 3); + assert_eq!(a.pop_first(), Some(1)); + assert_eq!(a.len(), 2); + assert_eq!(a.pop_last(), Some(3)); + assert_eq!(a.len(), 1); + assert_eq!(a.pop_first(), Some(2)); + assert_eq!(a.len(), 0); + assert_eq!(a.pop_last(), None); + assert_eq!(a.len(), 0); + assert_eq!(a.pop_first(), None); + assert_eq!(a.len(), 0); +} + fn rand_data(len: usize) -> Vec { let mut rng = DeterministicRng::new(); Vec::from_iter((0..len).map(|_| rng.next())) diff --git a/src/liballoc/tests/cow_str.rs b/src/liballoc/tests/cow_str.rs index 6f357eda9b..62a5c245a5 100644 --- a/src/liballoc/tests/cow_str.rs +++ b/src/liballoc/tests/cow_str.rs @@ -138,4 +138,7 @@ fn check_cow_clone_from() { let c2: Cow<'_, str> = Cow::Owned(s); c1.clone_from(&c2); assert!(c1.into_owned().capacity() >= 25); + let mut c3: Cow<'_, str> = Cow::Borrowed("bye"); + c3.clone_from(&c2); + assert_eq!(c2, c3); } diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 3273feb7b5..605e0ef55d 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -2,6 +2,7 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] +#![feature(map_first_last)] #![feature(new_uninit)] #![feature(pattern)] #![feature(trusted_len)] diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs index 8a26454c38..54a77d643c 100644 --- a/src/liballoc/tests/linked_list.rs +++ b/src/liballoc/tests/linked_list.rs @@ -1,4 +1,5 @@ use std::collections::LinkedList; +use std::panic::catch_unwind; #[test] fn test_basic() { @@ -102,7 +103,6 @@ fn test_split_off() { assert_eq!(m.back(), Some(&1)); assert_eq!(m.front(), Some(&1)); } - } #[test] @@ -305,8 +305,7 @@ fn test_show() { assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); - assert_eq!(format!("{:?}", list), - "[\"just\", \"one\", \"test\", \"more\"]"); + assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); } #[test] @@ -446,19 +445,14 @@ fn drain_filter_true() { #[test] fn drain_filter_complex() { - - { // [+xxx++++++xxxxx++++x+x++] + { + // [+xxx++++++xxxxx++++x+x++] let mut list = vec![ - 1, - 2, 4, 6, - 7, 9, 11, 13, 15, 17, - 18, 20, 22, 24, 26, - 27, 29, 31, 33, - 34, - 35, - 36, - 37, 39 - ].into_iter().collect::>(); + 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, + 39, + ] + .into_iter() + .collect::>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); @@ -471,17 +465,13 @@ fn drain_filter_complex() { ); } - { // [xxx++++++xxxxx++++x+x++] + { + // [xxx++++++xxxxx++++x+x++] let mut list = vec![ - 2, 4, 6, - 7, 9, 11, 13, 15, 17, - 18, 20, 22, 24, 26, - 27, 29, 31, 33, - 34, - 35, - 36, - 37, 39 - ].into_iter().collect::>(); + 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39, + ] + .into_iter() + .collect::>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); @@ -494,16 +484,12 @@ fn drain_filter_complex() { ); } - { // [xxx++++++xxxxx++++x+x] - let mut list = vec![ - 2, 4, 6, - 7, 9, 11, 13, 15, 17, - 18, 20, 22, 24, 26, - 27, 29, 31, 33, - 34, - 35, - 36 - ].into_iter().collect::>(); + { + // [xxx++++++xxxxx++++x+x] + let mut list = + vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36] + .into_iter() + .collect::>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); @@ -516,11 +502,11 @@ fn drain_filter_complex() { ); } - { // [xxxxxxxxxx+++++++++++] - let mut list = vec![ - 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, - 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 - ].into_iter().collect::>(); + { + // [xxxxxxxxxx+++++++++++] + let mut list = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] + .into_iter() + .collect::>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); @@ -530,11 +516,11 @@ fn drain_filter_complex() { assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); } - { // [+++++++++++xxxxxxxxxx] - let mut list = vec![ - 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, - 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 - ].into_iter().collect::>(); + { + // [+++++++++++xxxxxxxxxx] + let mut list = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + .into_iter() + .collect::>(); let removed = list.drain_filter(|x| *x % 2 == 0).collect::>(); assert_eq!(removed.len(), 10); @@ -544,3 +530,109 @@ fn drain_filter_complex() { assert_eq!(list.into_iter().collect::>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); } } + + +#[test] +fn test_drop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + drop(ring); + + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_with_pop() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + + drop(ring.pop_back()); + drop(ring.pop_front()); + assert_eq!(unsafe { DROPS }, 2); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_clear() { + static mut DROPS: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut ring = LinkedList::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + ring.clear(); + assert_eq!(unsafe { DROPS }, 4); + + drop(ring); + assert_eq!(unsafe { DROPS }, 4); +} + +#[test] +fn test_drop_panic() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + + catch_unwind(move || drop(q)).ok(); + + assert_eq!(unsafe { DROPS }, 8); +} diff --git a/src/liballoc/tests/rc.rs b/src/liballoc/tests/rc.rs index 7854ca0fc1..e77c57d9a5 100644 --- a/src/liballoc/tests/rc.rs +++ b/src/liballoc/tests/rc.rs @@ -1,9 +1,9 @@ use std::any::Any; -use std::rc::{Rc, Weak}; use std::cell::RefCell; use std::cmp::PartialEq; -use std::mem; use std::iter::TrustedLen; +use std::mem; +use std::rc::{Rc, Weak}; #[test] fn uninhabited() { @@ -12,7 +12,7 @@ fn uninhabited() { a = a.clone(); assert!(a.upgrade().is_none()); - let mut a: Weak = a; // Unsizing + let mut a: Weak = a; // Unsizing a = a.clone(); assert!(a.upgrade().is_none()); } @@ -20,8 +20,8 @@ fn uninhabited() { #[test] fn slice() { let a: Rc<[u32; 3]> = Rc::new([3, 2, 1]); - let a: Rc<[u32]> = a; // Unsizing - let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion + let a: Rc<[u32]> = a; // Unsizing + let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion assert_eq!(a, b); // Exercise is_dangling() with a DST @@ -33,7 +33,7 @@ fn slice() { #[test] fn trait_object() { let a: Rc = Rc::new(4); - let a: Rc = a; // Unsizing + let a: Rc = a; // Unsizing // Exercise is_dangling() with a DST let mut a = Rc::downgrade(&a); @@ -43,7 +43,7 @@ fn trait_object() { let mut b = Weak::::new(); b = b.clone(); assert!(b.upgrade().is_none()); - let mut b: Weak = b; // Unsizing + let mut b: Weak = b; // Unsizing b = b.clone(); assert!(b.upgrade().is_none()); } @@ -57,7 +57,7 @@ fn float_nan_ne() { #[test] fn partial_eq() { - struct TestPEq (RefCell); + struct TestPEq(RefCell); impl PartialEq for TestPEq { fn eq(&self, other: &TestPEq) -> bool { *self.0.borrow_mut() += 1; @@ -74,7 +74,7 @@ fn partial_eq() { #[test] fn eq() { #[derive(Eq)] - struct TestEq (RefCell); + struct TestEq(RefCell); impl PartialEq for TestEq { fn eq(&self, other: &TestEq) -> bool { *self.0.borrow_mut() += 1; @@ -156,13 +156,10 @@ fn shared_from_iter_trustedlen_normal() { fn shared_from_iter_trustedlen_panic() { // Exercise the `TrustedLen` implementation when `size_hint()` matches // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. - let iter = (0..SHARED_ITER_MAX) - .map(|val| { - match val { - 98 => panic!("I've almost got 99 problems."), - _ => Box::new(val), - } - }); + let iter = (0..SHARED_ITER_MAX).map(|val| match val { + 98 => panic!("I've almost got 99 problems."), + _ => Box::new(val), + }); assert_trusted_len(&iter); let _ = iter.collect::>(); @@ -189,16 +186,8 @@ fn shared_from_iter_trustedlen_no_fuse() { } } - let vec = vec![ - Some(Box::new(42)), - Some(Box::new(24)), - None, - Some(Box::new(12)), - ]; + let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))]; let iter = Iter(vec.into_iter()); assert_trusted_len(&iter); - assert_eq!( - &[Box::new(42), Box::new(24)], - &*iter.collect::>() - ); + assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::>()); } diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index ad2cd7c95e..ec45de7c79 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -4,7 +4,6 @@ use std::mem; use std::panic; use std::rc::Rc; use std::sync::atomic::{Ordering::Relaxed, AtomicUsize}; -use std::thread; use rand::{Rng, RngCore, thread_rng}; use rand::seq::SliceRandom; @@ -389,7 +388,7 @@ fn test_reverse() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn test_sort() { let mut rng = thread_rng(); @@ -1406,11 +1405,9 @@ fn test_box_slice_clone() { #[test] #[allow(unused_must_use)] // here, we care about the side effects of `.clone()` #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg(not(miri))] // Miri does not support threads fn test_box_slice_clone_panics() { use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; - use std::thread::spawn; struct Canary { count: Arc, @@ -1446,7 +1443,7 @@ fn test_box_slice_clone_panics() { panics: true, }; - spawn(move || { + std::panic::catch_unwind(move || { // When xs is dropped, +5. let xs = vec![canary.clone(), canary.clone(), canary.clone(), panic, canary] .into_boxed_slice(); @@ -1454,7 +1451,6 @@ fn test_box_slice_clone_panics() { // When panic is cloned, +3. xs.clone(); }) - .join() .unwrap_err(); // Total = 8 @@ -1566,7 +1562,7 @@ macro_rules! test { } let v = $input.to_owned(); - let _ = thread::spawn(move || { + let _ = std::panic::catch_unwind(move || { let mut v = v; let mut panic_countdown = panic_countdown; v.$func(|a, b| { @@ -1577,7 +1573,7 @@ macro_rules! test { panic_countdown -= 1; a.cmp(b) }) - }).join(); + }); // Check that the number of things dropped is exactly // what we expect (i.e., the contents of `v`). @@ -1598,7 +1594,6 @@ thread_local!(static SILENCE_PANIC: Cell = Cell::new(false)); #[test] #[cfg_attr(target_os = "emscripten", ignore)] // no threads -#[cfg(not(miri))] // Miri does not support threads fn panic_safe() { let prev = panic::take_hook(); panic::set_hook(Box::new(move |info| { @@ -1609,8 +1604,18 @@ fn panic_safe() { let mut rng = thread_rng(); - for len in (1..20).chain(70..MAX_LEN) { - for &modulus in &[5, 20, 50] { + #[cfg(not(miri))] // Miri is too slow + let lens = (1..20).chain(70..MAX_LEN); + #[cfg(not(miri))] // Miri is too slow + let moduli = &[5, 20, 50]; + + #[cfg(miri)] + let lens = 1..13; + #[cfg(miri)] + let moduli = &[10]; + + for len in lens { + for &modulus in moduli { for &has_runs in &[false, true] { let mut input = (0..len) .map(|id| { @@ -1643,6 +1648,9 @@ fn panic_safe() { } } } + + // Set default panic hook again. + drop(panic::take_hook()); } #[test] diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index cb73c7c179..1b011242d0 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -166,7 +166,7 @@ fn test_join_for_different_lengths_with_long_separator() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn test_unsafe_slice() { assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)}); assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)}); @@ -483,8 +483,8 @@ mod slice_index { } #[test] - #[cfg(not(target_os = "emscripten"))] // hits an OOM - #[cfg(not(miri))] // Miri is too slow + #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM + #[cfg_attr(miri, ignore)] // Miri is too slow fn simple_big() { fn a_million_letter_x() -> String { let mut i = 0; @@ -1069,7 +1069,7 @@ fn test_rev_iterator() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn test_chars_decoding() { let mut bytes = [0; 4]; for c in (0..0x110000).filter_map(std::char::from_u32) { @@ -1081,7 +1081,7 @@ fn test_chars_decoding() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn test_chars_rev_decoding() { let mut bytes = [0; 4]; for c in (0..0x110000).filter_map(std::char::from_u32) { @@ -1380,7 +1380,6 @@ fn test_bool_from_str() { assert_eq!("not even a boolean".parse::().ok(), None); } -#[cfg(not(miri))] // Miri is too slow fn check_contains_all_substrings(s: &str) { assert!(s.contains("")); for i in 0..s.len() { @@ -1391,7 +1390,7 @@ fn check_contains_all_substrings(s: &str) { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn strslice_issue_16589() { assert!("bananas".contains("nana")); @@ -1408,7 +1407,7 @@ fn strslice_issue_16878() { #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn test_strslice_contains() { let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'"; check_contains_all_substrings(x); diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 55edf56345..fe7b4ff24b 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -523,7 +523,7 @@ fn test_reserve_exact() { } #[test] -#[cfg(not(miri))] // Miri does not support signalling OOM +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM fn test_try_reserve() { // These are the interesting cases: @@ -601,7 +601,7 @@ fn test_try_reserve() { } #[test] -#[cfg(not(miri))] // Miri does not support signalling OOM +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM fn test_try_reserve_exact() { // This is exactly the same as test_try_reserve with the method changed. diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 8053721769..5e788d61f8 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -944,10 +944,9 @@ fn drain_filter_complex() { } } -// Miri does not support catching panics // FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] +#[cfg(not(target_os = "emscripten"))] fn drain_filter_consumed_panic() { use std::rc::Rc; use std::sync::Mutex; @@ -985,7 +984,7 @@ fn drain_filter_consumed_panic() { }; let drain = data.drain_filter(filter); - // NOTE: The DrainFilter is explictly consumed + // NOTE: The DrainFilter is explicitly consumed drain.for_each(drop); }); @@ -999,7 +998,7 @@ fn drain_filter_consumed_panic() { // FIXME: Re-enable emscripten once it can catch panics #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics +#[cfg(not(target_os = "emscripten"))] fn drain_filter_unconsumed_panic() { use std::rc::Rc; use std::sync::Mutex; @@ -1081,7 +1080,7 @@ fn test_reserve_exact() { } #[test] -#[cfg(not(miri))] // Miri does not support signalling OOM +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM fn test_try_reserve() { // These are the interesting cases: @@ -1184,7 +1183,7 @@ fn test_try_reserve() { } #[test] -#[cfg(not(miri))] // Miri does not support signalling OOM +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM fn test_try_reserve_exact() { // This is exactly the same as test_try_reserve with the method changed. diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index d49b553fc0..1ab3694a3c 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1,8 +1,9 @@ -use std::fmt::Debug; -use std::collections::{VecDeque, vec_deque::Drain}; use std::collections::TryReserveError::*; +use std::collections::{vec_deque::Drain, VecDeque}; +use std::fmt::Debug; use std::mem::size_of; -use std::{usize, isize}; +use std::panic::catch_unwind; +use std::{isize, usize}; use crate::hash; @@ -148,34 +149,20 @@ fn test_param_taggy() { #[test] fn test_param_taggypar() { - test_parameterized::>(Onepar::(1), - Twopar::(1, 2), - Threepar::(1, 2, 3), - Twopar::(17, 42)); + test_parameterized::>( + Onepar::(1), + Twopar::(1, 2), + Threepar::(1, 2, 3), + Twopar::(17, 42), + ); } #[test] fn test_param_reccy() { - let reccy1 = RecCy { - x: 1, - y: 2, - t: One(1), - }; - let reccy2 = RecCy { - x: 345, - y: 2, - t: Two(1, 2), - }; - let reccy3 = RecCy { - x: 1, - y: 777, - t: Three(1, 2, 3), - }; - let reccy4 = RecCy { - x: 19, - y: 252, - t: Two(17, 42), - }; + let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; + let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; + let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; + let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; test_parameterized::(reccy1, reccy2, reccy3, reccy4); } @@ -320,8 +307,7 @@ fn test_mut_rev_iter_wrap() { assert_eq!(d.pop_front(), Some(1)); d.push_back(4); - assert_eq!(d.iter_mut().rev().map(|x| *x).collect::>(), - vec![4, 3, 2]); + assert_eq!(d.iter_mut().rev().map(|x| *x).collect::>(), vec![4, 3, 2]); } #[test] @@ -372,7 +358,6 @@ fn test_mut_rev_iter() { #[test] fn test_into_iter() { - // Empty iter { let d: VecDeque = VecDeque::new(); @@ -431,7 +416,6 @@ fn test_into_iter() { #[test] fn test_drain() { - // Empty iter { let mut d: VecDeque = VecDeque::new(); @@ -650,12 +634,8 @@ fn test_show() { let ringbuf: VecDeque<_> = (0..10).collect(); assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"] - .iter() - .cloned() - .collect(); - assert_eq!(format!("{:?}", ringbuf), - "[\"just\", \"one\", \"test\", \"more\"]"); + let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); + assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]"); } #[test] @@ -730,6 +710,39 @@ fn test_drop_clear() { assert_eq!(unsafe { DROPS }, 4); } +#[test] +fn test_drop_panic() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = VecDeque::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + + catch_unwind(move || drop(q)).ok(); + + assert_eq!(unsafe { DROPS }, 8); +} + #[test] fn test_reserve_grow() { // test growth path A @@ -955,7 +968,6 @@ fn test_append_permutations() { // doesn't pop more values than are pushed for src_pop_back in 0..(src_push_back + src_push_front) { for src_pop_front in 0..(src_push_back + src_push_front - src_pop_back) { - let src = construct_vec_deque( src_push_back, src_pop_back, @@ -966,8 +978,8 @@ fn test_append_permutations() { for dst_push_back in 0..MAX { for dst_push_front in 0..MAX { for dst_pop_back in 0..(dst_push_back + dst_push_front) { - for dst_pop_front - in 0..(dst_push_back + dst_push_front - dst_pop_back) + for dst_pop_front in + 0..(dst_push_back + dst_push_front - dst_pop_back) { let mut dst = construct_vec_deque( dst_push_back, @@ -1122,9 +1134,8 @@ fn test_reserve_exact_2() { } #[test] -#[cfg(not(miri))] // Miri does not support signalling OOM +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM fn test_try_reserve() { - // These are the interesting cases: // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) // * > isize::MAX should always fail @@ -1158,22 +1169,27 @@ fn test_try_reserve() { if guards_against_isize { // Check isize::MAX + 1 does count as overflow if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { - } else { panic!("isize::MAX + 1 should trigger an overflow!") } + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } // Check usize::MAX does count as overflow if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { - } else { panic!("usize::MAX should trigger an overflow!") } + } else { + panic!("usize::MAX should trigger an overflow!") + } } else { // Check isize::MAX is an OOM // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) { - } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } } } - { // Same basic idea, but with non-zero len let mut ten_bytes: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); @@ -1186,33 +1202,42 @@ fn test_try_reserve() { } if guards_against_isize { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } } else { if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } } // Should always overflow in the add-to-len if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { - } else { panic!("usize::MAX should trigger an overflow!") } + } else { + panic!("usize::MAX should trigger an overflow!") + } } - { // Same basic idea, but with interesting type size let mut ten_u32s: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); } - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 10) { + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); } if guards_against_isize { - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { - } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } } else { - if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { - } else { panic!("isize::MAX + 1 should trigger an OOM!") } + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } } // Should fail in the mul-by-size if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { @@ -1220,13 +1245,11 @@ fn test_try_reserve() { panic!("usize::MAX should trigger an overflow!"); } } - } #[test] -#[cfg(not(miri))] // Miri does not support signalling OOM +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM fn test_try_reserve_exact() { - // This is exactly the same as test_try_reserve with the method changed. // See that test for comments. @@ -1247,21 +1270,26 @@ fn test_try_reserve_exact() { if guards_against_isize { if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { - } else { panic!("isize::MAX + 1 should trigger an overflow!") } + } else { + panic!("isize::MAX + 1 should trigger an overflow!") + } if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { - } else { panic!("usize::MAX should trigger an overflow!") } + } else { + panic!("usize::MAX should trigger an overflow!") + } } else { // Check isize::MAX is an OOM // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) { - } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } } } - { let mut ten_bytes: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); @@ -1273,36 +1301,46 @@ fn test_try_reserve_exact() { } if guards_against_isize { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } } else { if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { panic!("isize::MAX + 1 should trigger an OOM!") } + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { - } else { panic!("usize::MAX should trigger an overflow!") } + } else { + panic!("usize::MAX should trigger an overflow!") + } } - { let mut ten_u32s: VecDeque = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); } - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 10) { + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { panic!("isize::MAX shouldn't trigger an overflow!"); } if guards_against_isize { - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { - } else { panic!("isize::MAX + 1 should trigger an overflow!"); } + if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an overflow!"); + } } else { - if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { - } else { panic!("isize::MAX + 1 should trigger an OOM!") } + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { + } else { + panic!("isize::MAX + 1 should trigger an OOM!") + } } if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { - } else { panic!("usize::MAX should trigger an overflow!") } + } else { + panic!("usize::MAX should trigger an overflow!") + } } - } #[test] @@ -1404,9 +1442,8 @@ fn test_rotate_right_parts() { #[test] fn test_rotate_left_random() { let shifts = [ - 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, - 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, - 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3, + 12, 9, 11, 1, 7, 9, 7, 2, ]; let n = 12; let mut v: VecDeque<_> = (0..n).collect(); @@ -1423,9 +1460,8 @@ fn test_rotate_left_random() { #[test] fn test_rotate_right_random() { let shifts = [ - 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, - 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, - 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3, + 12, 9, 11, 1, 7, 9, 7, 2, ]; let n = 12; let mut v: VecDeque<_> = (0..n).collect(); @@ -1447,8 +1483,7 @@ fn test_try_fold_empty() { #[test] fn test_try_fold_none() { let v: VecDeque = (0..12).collect(); - assert_eq!(None, v.into_iter().try_fold(0, |a, b| - if b < 11 { Some(a + b) } else { None })); + assert_eq!(None, v.into_iter().try_fold(0, |a, b| if b < 11 { Some(a + b) } else { None })); } #[test] @@ -1463,7 +1498,6 @@ fn test_try_fold_unit() { assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(()))); } - #[test] fn test_try_fold_unit_none() { let v: std::collections::VecDeque<()> = [(); 10].iter().cloned().collect(); @@ -1534,7 +1568,7 @@ fn test_try_rfold_rotated() { #[test] fn test_try_rfold_moves_iter() { - let v : VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect(); + let v: VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect(); let mut iter = v.into_iter(); assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None); assert_eq!(iter.next_back(), Some(&70)); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5b53a6a289..2ad4e22884 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -92,7 +92,7 @@ use crate::raw_vec::RawVec; /// vec[0] = 7; /// assert_eq!(vec[0], 7); /// -/// vec.extend([1, 2, 3].iter().cloned()); +/// vec.extend([1, 2, 3].iter().copied()); /// /// for x in &vec { /// println!("{}", x); @@ -315,6 +315,10 @@ impl Vec { /// let mut vec: Vec = Vec::new(); /// ``` #[inline] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_vec_new", since = "1.32.0"), + )] #[stable(feature = "rust1", since = "1.0.0")] pub const fn new() -> Vec { Vec { @@ -629,6 +633,8 @@ impl Vec { /// The capacity will remain at least as large as both the length /// and the supplied value. /// + /// # Panics + /// /// Panics if the current capacity is smaller than the supplied /// minimum capacity. /// @@ -727,25 +733,20 @@ impl Vec { /// [`drain`]: #method.drain #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { - if mem::needs_drop::() { - let current_len = self.len; - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len); - // Set the final length at the end, keeping in mind that - // dropping an element might panic. Works around a missed - // optimization, as seen in the following issue: - // https://github.com/rust-lang/rust/issues/51802 - let mut local_len = SetLenOnDrop::new(&mut self.len); - - // drop any extra elements - for _ in len..current_len { - local_len.decrement_len(1); - ptr = ptr.offset(-1); - ptr::drop_in_place(ptr); - } + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + if len > self.len { + return; } - } else if len <= self.len { + let s = self.get_unchecked_mut(len..) as *mut _; self.len = len; + ptr::drop_in_place(s); } } @@ -861,7 +862,7 @@ impl Vec { /// /// [`truncate`]: #method.truncate /// [`resize`]: #method.resize - /// [`extend`]: #method.extend-1 + /// [`extend`]: ../../std/iter/trait.Extend.html#tymethod.extend /// [`clear`]: #method.clear /// /// # Safety @@ -1078,7 +1079,22 @@ impl Vec { pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool { - self.drain_filter(|x| !f(x)); + let len = self.len(); + let mut del = 0; + { + let v = &mut **self; + + for i in 0..len { + if !f(&v[i]) { + del += 1; + } else if del > 0 { + v.swap(i - del, i); + } + } + } + if del > 0 { + self.truncate(len - del); + } } /// Removes all but the first of consecutive elements in the vector that resolve to the same @@ -1338,10 +1354,9 @@ impl Vec { /// Splits the collection into two at the given index. /// - /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`, - /// and the returned `Self` contains elements `[at, len)`. - /// - /// Note that the capacity of `self` does not change. + /// Returns a newly allocated vector containing the elements in the range + /// `[at, len)`. After the call, the original vector will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. /// /// # Panics /// @@ -1630,11 +1645,6 @@ impl<'a> SetLenOnDrop<'a> { fn increment_len(&mut self, increment: usize) { self.local_len += increment; } - - #[inline] - fn decrement_len(&mut self, decrement: usize) { - self.local_len -= decrement; - } } impl Drop for SetLenOnDrop<'_> { @@ -2712,6 +2722,9 @@ impl ExactSizeIterator for Drain<'_, T> { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Drain<'_, T> {} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Drain<'_, T> {} @@ -2848,7 +2861,7 @@ pub struct DrainFilter<'a, T, F> old_len: usize, /// The filter test predicate. pred: F, - /// A flag that indicates a panic has occured in the filter test prodicate. + /// A flag that indicates a panic has occurred in the filter test prodicate. /// This is used as a hint in the drop implmentation to prevent consumption /// of the remainder of the `DrainFilter`. Any unprocessed items will be /// backshifted in the `vec`, but no further items will be dropped or diff --git a/src/libarena/Cargo.toml b/src/libarena/Cargo.toml index 2643912f6d..5158aab8b7 100644 --- a/src/libarena/Cargo.toml +++ b/src/libarena/Cargo.toml @@ -10,4 +10,4 @@ path = "lib.rs" [dependencies] rustc_data_structures = { path = "../librustc_data_structures" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 66d27a2751..854942dad3 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -202,53 +202,18 @@ impl TypedArena { #[inline] pub fn alloc_from_iter>(&self, iter: I) -> &mut [T] { assert!(mem::size_of::() != 0); - let mut iter = iter.into_iter(); - let size_hint = iter.size_hint(); - - match size_hint { - (min, Some(max)) if min == max => { - // We know the exact number of elements the iterator will produce here - let len = min; - - if len == 0 { - return &mut []; - } - - self.ensure_capacity(len); - - let slice = self.ptr.get(); - - unsafe { - let mut ptr = self.ptr.get(); - for _ in 0..len { - // Write into uninitialized memory. - ptr::write(ptr, iter.next().unwrap()); - // Advance the pointer. - ptr = ptr.offset(1); - // Update the pointer per iteration so if `iter.next()` panics - // we destroy the correct amount - self.ptr.set(ptr); - } - slice::from_raw_parts_mut(slice, len) - } - } - _ => { - cold_path(move || -> &mut [T] { - let mut vec: SmallVec<[_; 8]> = iter.collect(); - if vec.is_empty() { - return &mut []; - } - // Move the content to the arena by copying it and then forgetting - // the content of the SmallVec - unsafe { - let len = vec.len(); - let start_ptr = self.alloc_raw_slice(len); - vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); - vec.set_len(0); - slice::from_raw_parts_mut(start_ptr, len) - } - }) - } + let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); + if vec.is_empty() { + return &mut []; + } + // Move the content to the arena by copying it and then forgetting + // the content of the SmallVec + unsafe { + let len = vec.len(); + let start_ptr = self.alloc_raw_slice(len); + vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); + vec.set_len(0); + slice::from_raw_parts_mut(start_ptr, len) } } diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 5d0333d522..227b725de1 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -1,5 +1,7 @@ //! Memory allocation APIs +// ignore-tidy-undocumented-unsafe + #![stable(feature = "alloc_module", since = "1.28.0")] use crate::cmp; @@ -51,7 +53,7 @@ pub struct Layout { impl Layout { /// Constructs a `Layout` from a given `size` and `align`, - /// or returns `LayoutErr` if either of the following conditions + /// or returns `LayoutErr` if any of the following conditions /// are not met: /// /// * `align` must not be zero, @@ -98,6 +100,7 @@ impl Layout { /// This function is unsafe as it does not verify the preconditions from /// [`Layout::from_size_align`](#method.from_size_align). #[stable(feature = "alloc_layout", since = "1.28.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "alloc_layout", since = "1.28.0"))] #[inline] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) } @@ -135,7 +138,7 @@ impl Layout { #[inline] pub fn for_value(t: &T) -> Self { let (size, align) = (mem::size_of_val(t), mem::align_of_val(t)); - // See rationale in `new` for why this us using an unsafe variant below + // See rationale in `new` for why this is using an unsafe variant below debug_assert!(Layout::from_size_align(size, align).is_ok()); unsafe { Layout::from_size_align_unchecked(size, align) @@ -194,7 +197,7 @@ impl Layout { // valid. // // 2. `len + align - 1` can overflow by at most `align - 1`, - // so the &-mask wth `!(align - 1)` will ensure that in the + // so the &-mask with `!(align - 1)` will ensure that in the // case of overflow, `len_rounded_up` will itself be 0. // Thus the returned padding, when added to `len`, yields 0, // which trivially satisfies the alignment `align`. @@ -211,18 +214,19 @@ impl Layout { /// Creates a layout by rounding the size of this layout up to a multiple /// of the layout's alignment. /// - /// Returns `Err` if the padded size would overflow. - /// /// This is equivalent to adding the result of `padding_needed_for` /// to the layout's current size. #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[inline] - pub fn pad_to_align(&self) -> Result { + pub fn pad_to_align(&self) -> Layout { let pad = self.padding_needed_for(self.align()); - let new_size = self.size().checked_add(pad) - .ok_or(LayoutErr { private: () })?; + // This cannot overflow. Quoting from the invariant of Layout: + // > `size`, when rounded up to the nearest multiple of `align`, + // > must not overflow (i.e., the rounded value must be less than + // > `usize::MAX`) + let new_size = self.size() + pad; - Layout::from_size_align(new_size, self.align()) + Layout::from_size_align(new_size, self.align()).unwrap() } /// Creates a layout describing the record for `n` instances of @@ -236,10 +240,14 @@ impl Layout { #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[inline] pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> { - let padded_size = self.size().checked_add(self.padding_needed_for(self.align())) - .ok_or(LayoutErr { private: () })?; - let alloc_size = padded_size.checked_mul(n) + // Warning, removing the checked_add here led to segfaults in #67174. Further + // analysis in #69225 seems to indicate that this is an LTO-related + // miscompilation, so #67174 might be able to be reapplied in the future. + let padded_size = self + .size() + .checked_add(self.padding_needed_for(self.align())) .ok_or(LayoutErr { private: () })?; + let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?; unsafe { // self.align is already known to be valid and alloc_size has been @@ -250,7 +258,7 @@ impl Layout { /// Creates a layout describing the record for `self` followed by /// `next`, including any necessary padding to ensure that `next` - /// will be properly aligned. Note that the result layout will + /// will be properly aligned. Note that the resulting layout will /// satisfy the alignment properties of both `self` and `next`. /// /// The resulting layout will be the same as that of a C struct containing @@ -307,8 +315,7 @@ impl Layout { pub fn extend_packed(&self, next: Self) -> Result { let new_size = self.size().checked_add(next.size()) .ok_or(LayoutErr { private: () })?; - let layout = Layout::from_size_align(new_size, self.align())?; - Ok(layout) + Layout::from_size_align(new_size, self.align()) } /// Creates a layout describing the record for a `[T; n]`. @@ -385,7 +392,7 @@ impl fmt::Display for CannotReallocInPlace { } /// A memory allocator that can be registered as the standard library’s default -/// though the `#[global_allocator]` attributes. +/// through the `#[global_allocator]` attribute. /// /// Some of the methods require that a memory block be *currently /// allocated* via an allocator. This means that: @@ -456,7 +463,7 @@ pub unsafe trait GlobalAlloc { /// # Errors /// /// Returning a null pointer indicates that either memory is exhausted - /// or `layout` does not meet allocator's size or alignment constraints. + /// or `layout` does not meet this allocator's size or alignment constraints. /// /// Implementations are encouraged to return null on memory /// exhaustion rather than aborting, but this is not @@ -1043,7 +1050,7 @@ pub unsafe trait Alloc { /// Captures a common usage pattern for allocators. /// /// The returned block is suitable for passing to the - /// `alloc`/`realloc` methods of this allocator. + /// `realloc`/`dealloc` methods of this allocator. /// /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` /// must be considered "currently allocated" and must be @@ -1109,7 +1116,7 @@ pub unsafe trait Alloc { /// Captures a common usage pattern for allocators. /// /// The returned block is suitable for passing to the - /// `alloc`/`realloc` methods of this allocator. + /// `realloc`/`dealloc` methods of this allocator. /// /// Note to implementors: If this returns `Ok(ptr)`, then `ptr` /// must be considered "currently allocated" and must be @@ -1140,9 +1147,9 @@ pub unsafe trait Alloc { where Self: Sized { match Layout::array::(n) { - Ok(ref layout) if layout.size() > 0 => { + Ok(layout) if layout.size() > 0 => { unsafe { - self.alloc(layout.clone()).map(|p| p.cast()) + self.alloc(layout).map(|p| p.cast()) } } _ => Err(AllocErr), @@ -1156,7 +1163,7 @@ pub unsafe trait Alloc { /// Captures a common usage pattern for allocators. /// /// The returned block is suitable for passing to the - /// `alloc`/`realloc` methods of this allocator. + /// `realloc`/`dealloc` methods of this allocator. /// /// # Safety /// @@ -1190,9 +1197,9 @@ pub unsafe trait Alloc { where Self: Sized { match (Layout::array::(n_old), Layout::array::(n_new)) { - (Ok(ref k_old), Ok(ref k_new)) if k_old.size() > 0 && k_new.size() > 0 => { + (Ok(k_old), Ok(k_new)) if k_old.size() > 0 && k_new.size() > 0 => { debug_assert!(k_old.align() == k_new.align()); - self.realloc(ptr.cast(), k_old.clone(), k_new.size()).map(NonNull::cast) + self.realloc(ptr.cast(), k_old, k_new.size()).map(NonNull::cast) } _ => { Err(AllocErr) @@ -1224,8 +1231,8 @@ pub unsafe trait Alloc { where Self: Sized { match Layout::array::(n) { - Ok(ref k) if k.size() > 0 => { - Ok(self.dealloc(ptr.cast(), k.clone())) + Ok(k) if k.size() > 0 => { + Ok(self.dealloc(ptr.cast(), k)) } _ => { Err(AllocErr) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index e2704e807d..7935c9b1b3 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -68,7 +68,7 @@ use crate::intrinsics; // Any trait /////////////////////////////////////////////////////////////////////////////// -/// A type to emulate dynamic typing. +/// A trait to emulate dynamic typing. /// /// Most types implement `Any`. However, any type which contains a non-`'static` reference does not. /// See the [module-level documentation][mod] for more details. @@ -182,6 +182,7 @@ impl dyn Any { #[inline] pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { + // SAFETY: just checked whether we are pointing to the correct type unsafe { Some(&*(self as *const dyn Any as *const T)) } @@ -217,6 +218,7 @@ impl dyn Any { #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { + // SAFETY: just checked whether we are pointing to the correct type unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) } @@ -421,10 +423,15 @@ impl TypeId { /// assert_eq!(is_string(&"cookie monster".to_string()), true); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature="const_type_id")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature="const_type_id"))] + #[cfg_attr(not(bootstrap), rustc_const_unstable(feature="const_type_id", issue = "41875"))] pub const fn of() -> TypeId { TypeId { + #[cfg(bootstrap)] + // SAFETY: going away soon t: unsafe { intrinsics::type_id::() }, + #[cfg(not(bootstrap))] + t: intrinsics::type_id::(), } } } @@ -446,7 +453,7 @@ impl TypeId { /// The current implementation uses the same infrastructure as compiler /// diagnostics and debuginfo, but this is not guaranteed. /// -/// # Example +/// # Examples /// /// ```rust /// assert_eq!( @@ -455,7 +462,48 @@ impl TypeId { /// ); /// ``` #[stable(feature = "type_name", since = "1.38.0")] -#[rustc_const_unstable(feature = "const_type_name")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_name"))] +#[cfg_attr(not(bootstrap), rustc_const_unstable(feature = "const_type_name", issue = "63084"))] pub const fn type_name() -> &'static str { intrinsics::type_name::() } + +/// Returns the name of the type of the pointed-to value as a string slice. +/// This is the same as `type_name::()`, but can be used where the type of a +/// variable is not easily available. +/// +/// # Note +/// +/// This is intended for diagnostic use. The exact contents and format of the +/// string are not specified, other than being a best-effort description of the +/// type. For example, `type_name_of::>(None)` could return +/// `"Option"` or `"std::option::Option"`, but not +/// `"foobar"`. In addition, the output may change between versions of the +/// compiler. +/// +/// The type name should not be considered a unique identifier of a type; +/// multiple types may share the same type name. +/// +/// The current implementation uses the same infrastructure as compiler +/// diagnostics and debuginfo, but this is not guaranteed. +/// +/// # Examples +/// +/// Prints the default integer and float types. +/// +/// ```rust +/// #![feature(type_name_of_val)] +/// use std::any::type_name_of_val; +/// +/// let x = 1; +/// println!("{}", type_name_of_val(&x)); +/// let y = 1.0; +/// println!("{}", type_name_of_val(&y)); +/// ``` +#[unstable(feature = "type_name_of_val", issue = "66359")] +#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_name"))] +#[cfg_attr(not(bootstrap), rustc_const_unstable(feature = "const_type_name", issue = "63084"))] +pub const fn type_name_of_val(val: &T) -> &'static str { + let _ = val; + type_name::() +} diff --git a/src/libcore/array/iter.rs b/src/libcore/array/iter.rs index 1180323840..aab9463e3a 100644 --- a/src/libcore/array/iter.rs +++ b/src/libcore/array/iter.rs @@ -51,7 +51,7 @@ where /// iterator (either via `IntoIterator` for arrays or via another way). #[unstable(feature = "array_value_iter", issue = "65798")] pub fn new(array: [T; N]) -> Self { - // The transmute here is actually safe. The docs of `MaybeUninit` + // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit` // promise: // // > `MaybeUninit` is guaranteed to have the same size and alignment @@ -84,14 +84,26 @@ where /// Returns an immutable slice of all elements that have not been yielded /// yet. fn as_slice(&self) -> &[T] { - // This transmute is safe. As mentioned in `new`, `MaybeUninit` retains + let slice = &self.data[self.alive.clone()]; + // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains // the size and alignment of `T`. Furthermore, we know that all // elements within `alive` are properly initialized. - let slice = &self.data[self.alive.clone()]; unsafe { mem::transmute::<&[MaybeUninit], &[T]>(slice) } } + + /// Returns a mutable slice of all elements that have not been yielded yet. + fn as_mut_slice(&mut self) -> &mut [T] { + // This transmute is safe, same as in `as_slice` above. + let slice = &mut self.data[self.alive.clone()]; + // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains + // the size and alignment of `T`. Furthermore, we know that all + // elements within `alive` are properly initialized. + unsafe { + mem::transmute::<&mut [MaybeUninit], &mut [T]>(slice) + } + } } @@ -117,7 +129,8 @@ where let idx = self.alive.start; self.alive.start += 1; - // Read the element from the array. This is safe: `idx` is an index + // Read the element from the array. + // SAFETY: This is safe: `idx` is an index // into the "alive" region of the array. Reading this element means // that `data[idx]` is regarded as dead now (i.e. do not touch). As // `idx` was the start of the alive-zone, the alive zone is now @@ -163,7 +176,8 @@ where // + 1]`. self.alive.end -= 1; - // Read the element from the array. This is safe: `alive.end` is an + // Read the element from the array. + // SAFETY: This is safe: `alive.end` is an // index into the "alive" region of the array. Compare the previous // comment that states that the alive region is // `data[alive.start..alive.end + 1]`. Reading this element means that @@ -182,10 +196,12 @@ where [T; N]: LengthAtMost32, { fn drop(&mut self) { - // We simply drop each element via `for_each`. This should not incur - // any significant runtime overhead and avoids adding another `unsafe` - // block. - self.by_ref().for_each(drop); + // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice + // of elements that have not been moved out yet and that remain + // to be dropped. + unsafe { + ptr::drop_in_place(self.as_mut_slice()) + } } } @@ -226,6 +242,7 @@ where [T; N]: LengthAtMost32, { fn clone(&self) -> Self { + // SAFETY: each point of unsafety is documented inside the unsafe block unsafe { // This creates a new uninitialized array. Note that the `assume_init` // refers to the array, not the individual elements. And it is Ok if diff --git a/src/libcore/array/mod.rs b/src/libcore/array/mod.rs index e1ec8b795d..38d248d701 100644 --- a/src/libcore/array/mod.rs +++ b/src/libcore/array/mod.rs @@ -1,5 +1,5 @@ //! Implementations of things like `Eq` for fixed-length arrays -//! up to a certain length. Eventually we should able to generalize +//! up to a certain length. Eventually, we should be able to generalize //! to all lengths. //! //! *[See also the array primitive type](../../std/primitive.array.html).* @@ -14,10 +14,8 @@ use crate::hash::{Hash, self}; use crate::marker::Unsize; use crate::slice::{Iter, IterMut}; -#[cfg(not(bootstrap))] mod iter; -#[cfg(not(bootstrap))] #[unstable(feature = "array_value_iter", issue = "65798")] pub use iter::IntoIter; @@ -156,6 +154,7 @@ where fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> { if slice.len() == N { let ptr = slice.as_ptr() as *const [T; N]; + // SAFETY: ok because we just checked that the length fits unsafe { Ok(&*ptr) } } else { Err(TryFromSliceError(())) @@ -173,6 +172,7 @@ where fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> { if slice.len() == N { let ptr = slice.as_mut_ptr() as *mut [T; N]; + // SAFETY: ok because we just checked that the length fits unsafe { Ok(&mut *ptr) } } else { Err(TryFromSliceError(())) diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index 4087333e2c..e78dfd1ed4 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -12,8 +12,8 @@ #![stable(feature = "core_ascii", since = "1.26.0")] use crate::fmt; -use crate::ops::Range; use crate::iter::FusedIterator; +use crate::ops::Range; use crate::str::from_utf8_unchecked; /// An iterator over the escaped version of a byte. @@ -100,7 +100,7 @@ pub fn escape_default(c: u8) -> EscapeDefault { b'\\' => ([b'\\', b'\\', 0, 0], 2), b'\'' => ([b'\\', b'\'', 0, 0], 2), b'"' => ([b'\\', b'"', 0, 0], 2), - b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1), + b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1), _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), }; @@ -108,7 +108,7 @@ pub fn escape_default(c: u8) -> EscapeDefault { fn hexify(b: u8) -> u8 { match b { - 0 ..= 9 => b'0' + b, + 0..=9 => b'0' + b, _ => b'a' + b - 10, } } @@ -117,9 +117,15 @@ pub fn escape_default(c: u8) -> EscapeDefault { #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeDefault { type Item = u8; - fn next(&mut self) -> Option { self.range.next().map(|i| self.data[i]) } - fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } - fn last(mut self) -> Option { self.next_back() } + fn next(&mut self) -> Option { + self.range.next().map(|i| self.data[i]) + } + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { @@ -135,6 +141,7 @@ impl FusedIterator for EscapeDefault {} #[stable(feature = "ascii_escape_display", since = "1.39.0")] impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // SAFETY: ok because `escape_default` created only valid utf-8 data f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) }) } } diff --git a/src/libcore/benches/any.rs b/src/libcore/benches/any.rs index ceb507aad3..53099b7826 100644 --- a/src/libcore/benches/any.rs +++ b/src/libcore/benches/any.rs @@ -1,5 +1,5 @@ use core::any::*; -use test::{Bencher, black_box}; +use test::{black_box, Bencher}; #[bench] fn bench_downcast_ref(b: &mut Bencher) { diff --git a/src/libcore/benches/ascii.rs b/src/libcore/benches/ascii.rs index a337c46713..76ccd3ddb6 100644 --- a/src/libcore/benches/ascii.rs +++ b/src/libcore/benches/ascii.rs @@ -22,17 +22,9 @@ // // Therefore: fn branchless_to_ascii_upper_case(byte: u8) -> u8 { - byte & - !( - ( - byte.wrapping_add(0x1f) & - !byte.wrapping_add(0x05) & - 0x80 - ) >> 2 - ) + byte & !((byte.wrapping_add(0x1f) & !byte.wrapping_add(0x05) & 0x80) >> 2) } - macro_rules! benches { ($( fn $name: ident($arg: ident: &mut [u8]) $body: block )+ @iter $( $is_: ident, )+) => { benches! {@ @@ -118,6 +110,7 @@ benches! { } fn case07_fake_simd_u32(bytes: &mut [u8]) { + // SAFETY: transmuting a sequence of `u8` to `u32` is always fine let (before, aligned, after) = unsafe { bytes.align_to_mut::() }; @@ -142,6 +135,7 @@ benches! { } fn case08_fake_simd_u64(bytes: &mut [u8]) { + // SAFETY: transmuting a sequence of `u8` to `u64` is always fine let (before, aligned, after) = unsafe { bytes.align_to_mut::() }; @@ -252,12 +246,15 @@ benches! { } macro_rules! repeat { - ($s: expr) => { concat!($s, $s, $s, $s, $s, $s, $s, $s, $s, $s) } + ($s: expr) => { + concat!($s, $s, $s, $s, $s, $s, $s, $s, $s, $s) + }; } const SHORT: &'static str = "Alice's"; const MEDIUM: &'static str = "Alice's Adventures in Wonderland"; -const LONG: &'static str = repeat!(r#" +const LONG: &'static str = repeat!( + r#" La Guida di Bragia, a Ballad Opera for the Marionette Theatre (around 1850) Alice's Adventures in Wonderland (1865) Phantasmagoria and Other Poems (1869) @@ -273,8 +270,10 @@ const LONG: &'static str = repeat!(r#" What the Tortoise Said to Achilles (1895) Three Sunsets and Other Poems (1898) The Manlet (1903)[106] -"#); +"# +); +#[rustfmt::skip] const ASCII_UPPERCASE_MAP: [u8; 256] = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, @@ -328,6 +327,7 @@ enum AsciiCharacterClass { } use self::AsciiCharacterClass::*; +#[rustfmt::skip] static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 256] = [ // _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_ diff --git a/src/libcore/benches/char/methods.rs b/src/libcore/benches/char/methods.rs index af934c1171..a9a08a4d76 100644 --- a/src/libcore/benches/char/methods.rs +++ b/src/libcore/benches/char/methods.rs @@ -25,8 +25,13 @@ fn bench_to_digit_radix_36(b: &mut Bencher) { #[bench] fn bench_to_digit_radix_var(b: &mut Bencher) { - b.iter(|| CHARS.iter().cycle() - .zip(RADIX.iter().cycle()) - .take(10_000) - .map(|(c, radix)| c.to_digit(*radix)).min()) + b.iter(|| { + CHARS + .iter() + .cycle() + .zip(RADIX.iter().cycle()) + .take(10_000) + .map(|(c, radix)| c.to_digit(*radix)) + .min() + }) } diff --git a/src/libcore/benches/fmt.rs b/src/libcore/benches/fmt.rs index 92f10c760c..dd72a33996 100644 --- a/src/libcore/benches/fmt.rs +++ b/src/libcore/benches/fmt.rs @@ -1,5 +1,5 @@ -use std::io::{self, Write as IoWrite}; use std::fmt::{self, Write as FmtWrite}; +use std::io::{self, Write as IoWrite}; use test::Bencher; #[bench] diff --git a/src/libcore/benches/hash/sip.rs b/src/libcore/benches/hash/sip.rs index 5baba42763..725c864dce 100644 --- a/src/libcore/benches/hash/sip.rs +++ b/src/libcore/benches/hash/sip.rs @@ -1,7 +1,7 @@ #![allow(deprecated)] use core::hash::*; -use test::{Bencher, black_box}; +use test::{black_box, Bencher}; fn hash_bytes(mut s: H, x: &[u8]) -> u64 { Hasher::write(&mut s, x); @@ -44,11 +44,11 @@ fn bench_str_over_8_bytes(b: &mut Bencher) { #[bench] fn bench_long_str(b: &mut Bencher) { let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \ -incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \ -exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \ -irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \ -pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \ -officia deserunt mollit anim id est laborum."; + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \ + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \ + irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \ + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \ + officia deserunt mollit anim id est laborum."; b.iter(|| { assert_eq!(hash(&s), 17717065544121360093); }) @@ -58,9 +58,7 @@ officia deserunt mollit anim id est laborum."; fn bench_u32(b: &mut Bencher) { let u = 162629500u32; let u = black_box(u); - b.iter(|| { - hash(&u) - }); + b.iter(|| hash(&u)); b.bytes = 8; } @@ -70,9 +68,7 @@ fn bench_u32_keyed(b: &mut Bencher) { let u = black_box(u); let k1 = black_box(0x1); let k2 = black_box(0x2); - b.iter(|| { - hash_with(SipHasher::new_with_keys(k1, k2), &u) - }); + b.iter(|| hash_with(SipHasher::new_with_keys(k1, k2), &u)); b.bytes = 8; } @@ -80,62 +76,48 @@ fn bench_u32_keyed(b: &mut Bencher) { fn bench_u64(b: &mut Bencher) { let u = 16262950014981195938u64; let u = black_box(u); - b.iter(|| { - hash(&u) - }); + b.iter(|| hash(&u)); b.bytes = 8; } #[bench] fn bench_bytes_4(b: &mut Bencher) { let data = black_box([b' '; 4]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); + b.iter(|| hash_bytes(SipHasher::default(), &data)); b.bytes = 4; } #[bench] fn bench_bytes_7(b: &mut Bencher) { let data = black_box([b' '; 7]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); + b.iter(|| hash_bytes(SipHasher::default(), &data)); b.bytes = 7; } #[bench] fn bench_bytes_8(b: &mut Bencher) { let data = black_box([b' '; 8]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); + b.iter(|| hash_bytes(SipHasher::default(), &data)); b.bytes = 8; } #[bench] fn bench_bytes_a_16(b: &mut Bencher) { let data = black_box([b' '; 16]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); + b.iter(|| hash_bytes(SipHasher::default(), &data)); b.bytes = 16; } #[bench] fn bench_bytes_b_32(b: &mut Bencher) { let data = black_box([b' '; 32]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); + b.iter(|| hash_bytes(SipHasher::default(), &data)); b.bytes = 32; } #[bench] fn bench_bytes_c_128(b: &mut Bencher) { let data = black_box([b' '; 128]); - b.iter(|| { - hash_bytes(SipHasher::default(), &data) - }); + b.iter(|| hash_bytes(SipHasher::default(), &data)); b.bytes = 128; } diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 7dcfad8306..fb6b4b7837 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -1,5 +1,5 @@ use core::iter::*; -use test::{Bencher, black_box}; +use test::{black_box, Bencher}; #[bench] fn bench_rposition(b: &mut Bencher) { @@ -14,7 +14,11 @@ fn bench_skip_while(b: &mut Bencher) { b.iter(|| { let it = 0..100; let mut sum = 0; - it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true); + it.skip_while(|&x| { + sum += x; + sum < 4000 + }) + .all(|_| true); }); } @@ -29,7 +33,9 @@ fn bench_multiple_take(b: &mut Bencher) { }); } -fn scatter(x: i32) -> i32 { (x * 31) % 127 } +fn scatter(x: i32) -> i32 { + (x * 31) % 127 +} #[bench] fn bench_max_by_key(b: &mut Bencher) { @@ -76,23 +82,21 @@ pub fn add_zip(xs: &[f32], ys: &mut [f32]) { fn bench_zip_copy(b: &mut Bencher) { let source = vec![0u8; 16 * 1024]; let mut dst = black_box(vec![0u8; 16 * 1024]); - b.iter(|| { - copy_zip(&source, &mut dst) - }) + b.iter(|| copy_zip(&source, &mut dst)) } #[bench] fn bench_zip_add(b: &mut Bencher) { let source = vec![1.; 16 * 1024]; let mut dst = vec![0.; 16 * 1024]; - b.iter(|| { - add_zip(&source, &mut dst) - }); + b.iter(|| add_zip(&source, &mut dst)); } /// `Iterator::for_each` implemented as a plain loop. -fn for_each_loop(iter: I, mut f: F) where - I: Iterator, F: FnMut(I::Item) +fn for_each_loop(iter: I, mut f: F) +where + I: Iterator, + F: FnMut(I::Item), { for item in iter { f(item); @@ -101,8 +105,10 @@ fn for_each_loop(iter: I, mut f: F) where /// `Iterator::for_each` implemented with `fold` for internal iteration. /// (except when `by_ref()` effectively disables that optimization.) -fn for_each_fold(iter: I, mut f: F) where - I: Iterator, F: FnMut(I::Item) +fn for_each_fold(iter: I, mut f: F) +where + I: Iterator, + F: FnMut(I::Item), { iter.fold((), move |(), item| f(item)); } @@ -137,25 +143,20 @@ fn bench_for_each_chain_ref_fold(b: &mut Bencher) { }); } - /// Helper to benchmark `sum` for iterators taken by value which /// can optimize `fold`, and by reference which cannot. macro_rules! bench_sums { ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => { #[bench] fn $bench_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - $iter.map(black_box).sum() - }); + b.iter(|| -> i64 { $iter.map(black_box).sum() }); } #[bench] fn $bench_ref_sum(b: &mut Bencher) { - b.iter(|| -> i64 { - $iter.map(black_box).by_ref().sum() - }); + b.iter(|| -> i64 { $iter.map(black_box).by_ref().sum() }); } - } + }; } bench_sums! { @@ -286,7 +287,10 @@ fn bench_zip_then_skip(b: &mut Bencher) { let t: Vec<_> = (0..100_000).collect(); b.iter(|| { - let s = v.iter().zip(t.iter()).skip(10000) + let s = v + .iter() + .zip(t.iter()) + .skip(10000) .take_while(|t| *t.0 < 10100) .map(|(a, b)| *a + *b) .sum::(); @@ -299,7 +303,10 @@ fn bench_skip_then_zip(b: &mut Bencher) { let t: Vec<_> = (0..100_000).collect(); b.iter(|| { - let s = v.iter().skip(10000).zip(t.iter().skip(10000)) + let s = v + .iter() + .skip(10000) + .zip(t.iter().skip(10000)) .take_while(|t| *t.0 < 10100) .map(|(a, b)| *a + *b) .sum::(); @@ -309,23 +316,17 @@ fn bench_skip_then_zip(b: &mut Bencher) { #[bench] fn bench_filter_count(b: &mut Bencher) { - b.iter(|| { - (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count() - }) + b.iter(|| (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()) } #[bench] fn bench_filter_ref_count(b: &mut Bencher) { - b.iter(|| { - (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count() - }) + b.iter(|| (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()) } #[bench] fn bench_filter_chain_count(b: &mut Bencher) { - b.iter(|| { - (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count() - }) + b.iter(|| (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()) } #[bench] diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index dea2963d9a..570fc4ab93 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -6,9 +6,10 @@ extern crate test; mod any; mod ascii; mod char; +mod fmt; mod hash; mod iter; mod num; mod ops; +mod pattern; mod slice; -mod fmt; diff --git a/src/libcore/benches/num/flt2dec/mod.rs b/src/libcore/benches/num/flt2dec/mod.rs index 4153745d04..b810dd12ab 100644 --- a/src/libcore/benches/num/flt2dec/mod.rs +++ b/src/libcore/benches/num/flt2dec/mod.rs @@ -3,17 +3,17 @@ mod strategy { mod grisu; } +use core::num::flt2dec::MAX_SIG_DIGITS; +use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded}; use std::f64; use std::io::Write; use std::vec::Vec; use test::Bencher; -use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; -use core::num::flt2dec::MAX_SIG_DIGITS; pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { FullDecoded::Finite(decoded) => decoded, - full_decoded => panic!("expected finite, got {:?} instead", full_decoded) + full_decoded => panic!("expected finite, got {:?} instead", full_decoded), } } diff --git a/src/libcore/benches/num/flt2dec/strategy/dragon.rs b/src/libcore/benches/num/flt2dec/strategy/dragon.rs index 60660b1da1..4052fec338 100644 --- a/src/libcore/benches/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/benches/num/flt2dec/strategy/dragon.rs @@ -1,6 +1,6 @@ -use std::{i16, f64}; use super::super::*; use core::num::flt2dec::strategy::dragon::*; +use std::{f64, i16}; use test::Bencher; #[bench] diff --git a/src/libcore/benches/num/flt2dec/strategy/grisu.rs b/src/libcore/benches/num/flt2dec/strategy/grisu.rs index 841feba50d..495074747c 100644 --- a/src/libcore/benches/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/benches/num/flt2dec/strategy/grisu.rs @@ -1,12 +1,12 @@ -use std::{i16, f64}; use super::super::*; use core::num::flt2dec::strategy::grisu::*; +use std::{f64, i16}; use test::Bencher; pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { FullDecoded::Finite(decoded) => decoded, - full_decoded => panic!("expected finite, got {:?} instead", full_decoded) + full_decoded => panic!("expected finite, got {:?} instead", full_decoded), } } diff --git a/src/libcore/benches/num/mod.rs b/src/libcore/benches/num/mod.rs index f5c49ea5bf..852d4e481e 100644 --- a/src/libcore/benches/num/mod.rs +++ b/src/libcore/benches/num/mod.rs @@ -1,8 +1,8 @@ -mod flt2dec; mod dec2flt; +mod flt2dec; -use test::Bencher; use std::str::FromStr; +use test::Bencher; const ASCII_NUMBERS: [&str; 19] = [ "0", @@ -27,7 +27,7 @@ const ASCII_NUMBERS: [&str; 19] = [ ]; macro_rules! from_str_bench { - ($mac:ident, $t:ty) => ( + ($mac:ident, $t:ty) => { #[bench] fn $mac(b: &mut Bencher) { b.iter(|| { @@ -35,15 +35,15 @@ macro_rules! from_str_bench { .iter() .cycle() .take(5_000) - .filter_map(|s| <($t)>::from_str(s).ok()) + .filter_map(|s| <$t>::from_str(s).ok()) .max() }) } - ) + }; } macro_rules! from_str_radix_bench { - ($mac:ident, $t:ty, $radix:expr) => ( + ($mac:ident, $t:ty, $radix:expr) => { #[bench] fn $mac(b: &mut Bencher) { b.iter(|| { @@ -51,11 +51,11 @@ macro_rules! from_str_radix_bench { .iter() .cycle() .take(5_000) - .filter_map(|s| <($t)>::from_str_radix(s, $radix).ok()) + .filter_map(|s| <$t>::from_str_radix(s, $radix).ok()) .max() }) } - ) + }; } from_str_bench!(bench_u8_from_str, u8); diff --git a/src/libcore/benches/ops.rs b/src/libcore/benches/ops.rs index 80649f3356..0a2be8a288 100644 --- a/src/libcore/benches/ops.rs +++ b/src/libcore/benches/ops.rs @@ -4,17 +4,16 @@ use test::Bencher; // Overhead of dtors struct HasDtor { - _x: isize + _x: isize, } impl Drop for HasDtor { - fn drop(&mut self) { - } + fn drop(&mut self) {} } #[bench] fn alloc_obj_with_dtor(b: &mut Bencher) { b.iter(|| { - HasDtor { _x : 10 }; + HasDtor { _x: 10 }; }) } diff --git a/src/libcore/benches/pattern.rs b/src/libcore/benches/pattern.rs new file mode 100644 index 0000000000..a49490cec1 --- /dev/null +++ b/src/libcore/benches/pattern.rs @@ -0,0 +1,43 @@ +use test::black_box; +use test::Bencher; + +#[bench] +fn starts_with_char(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.starts_with('k')); + } + }) +} + +#[bench] +fn starts_with_str(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.starts_with("k")); + } + }) +} + + +#[bench] +fn ends_with_char(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.ends_with('k')); + } + }) +} + +#[bench] +fn ends_with_str(b: &mut Bencher) { + let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind"); + b.iter(|| { + for _ in 0..1024 { + black_box(text.ends_with("k")); + } + }) +} diff --git a/src/libcore/benches/slice.rs b/src/libcore/benches/slice.rs index 711a8dff2c..06b37cb084 100644 --- a/src/libcore/benches/slice.rs +++ b/src/libcore/benches/slice.rs @@ -8,11 +8,12 @@ enum Cache { } fn binary_search(b: &mut Bencher, cache: Cache, mapper: F) - where F: Fn(usize) -> usize +where + F: Fn(usize) -> usize, { let size = match cache { - Cache::L1 => 1000, // 8kb - Cache::L2 => 10_000, // 80kb + Cache::L1 => 1000, // 8kb + Cache::L2 => 10_000, // 80kb Cache::L3 => 1_000_000, // 8Mb }; let v = (0..size).map(&mapper).collect::>(); diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index 617bdd238f..6e0865e865 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -9,17 +9,13 @@ impl bool { /// ``` /// #![feature(bool_to_option)] /// - /// assert_eq!(false.then(0), None); - /// assert_eq!(true.then(0), Some(0)); + /// assert_eq!(false.then_some(0), None); + /// assert_eq!(true.then_some(0), Some(0)); /// ``` #[unstable(feature = "bool_to_option", issue = "64260")] #[inline] - pub fn then(self, t: T) -> Option { - if self { - Some(t) - } else { - None - } + pub fn then_some(self, t: T) -> Option { + if self { Some(t) } else { None } } /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise. @@ -29,16 +25,12 @@ impl bool { /// ``` /// #![feature(bool_to_option)] /// - /// assert_eq!(false.then_with(|| 0), None); - /// assert_eq!(true.then_with(|| 0), Some(0)); + /// assert_eq!(false.then(|| 0), None); + /// assert_eq!(true.then(|| 0), Some(0)); /// ``` #[unstable(feature = "bool_to_option", issue = "64260")] #[inline] - pub fn then_with T>(self, f: F) -> Option { - if self { - Some(f()) - } else { - None - } + pub fn then T>(self, f: F) -> Option { + if self { Some(f()) } else { None } } } diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index fda103a52d..e4b4cd31c6 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -137,9 +137,11 @@ //! use std::cell::Cell; //! use std::ptr::NonNull; //! use std::intrinsics::abort; +//! use std::marker::PhantomData; //! //! struct Rc { -//! ptr: NonNull> +//! ptr: NonNull>, +//! phantom: PhantomData>, //! } //! //! struct RcBox { @@ -151,7 +153,10 @@ //! impl Clone for Rc { //! fn clone(&self) -> Rc { //! self.inc_strong(); -//! Rc { ptr: self.ptr } +//! Rc { +//! ptr: self.ptr, +//! phantom: PhantomData, +//! } //! } //! } //! @@ -182,6 +187,8 @@ //! ``` //! +// ignore-tidy-undocumented-unsafe + #![stable(feature = "rust1", since = "1.0.0")] use crate::cmp::Ordering; @@ -317,6 +324,7 @@ impl Cell { /// let c = Cell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_cell_new", since = "1.32.0"))] #[inline] pub const fn new(value: T) -> Cell { Cell { @@ -462,6 +470,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0"))] pub const fn as_ptr(&self) -> *mut T { self.value.get() } @@ -642,6 +651,7 @@ impl RefCell { /// let c = RefCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_refcell_new", since = "1.32.0"))] #[inline] pub const fn new(value: T) -> RefCell { RefCell { @@ -1494,6 +1504,10 @@ impl UnsafeCell { /// let uc = UnsafeCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_unsafe_cell_new", since = "1.32.0"), + )] #[inline] pub const fn new(value: T) -> UnsafeCell { UnsafeCell { value } @@ -1536,11 +1550,52 @@ impl UnsafeCell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0"), + )] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of - // #[repr(transparent)] + // #[repr(transparent)]. This exploits libstd's special status, there is + // no guarantee for user code that this will work in future versions of the compiler! self as *const UnsafeCell as *const T as *mut T } + + /// Gets a mutable pointer to the wrapped value. + /// The difference to [`get`] is that this function accepts a raw pointer, + /// which is useful to avoid the creation of temporary references. + /// + /// The result can be cast to a pointer of any kind. + /// Ensure that the access is unique (no active references, mutable or not) + /// when casting to `&mut T`, and ensure that there are no mutations + /// or mutable aliases going on when casting to `&T`. + /// + /// [`get`]: #method.get + /// + /// # Examples + /// + /// Gradual initialization of an `UnsafeCell` requires `raw_get`, as + /// calling `get` would require creating a reference to uninitialized data: + /// + /// ``` + /// #![feature(unsafe_cell_raw_get)] + /// use std::cell::UnsafeCell; + /// use std::mem::MaybeUninit; + /// + /// let m = MaybeUninit::>::uninit(); + /// unsafe { UnsafeCell::raw_get(m.as_ptr()).write(5); } + /// let uc = unsafe { m.assume_init() }; + /// + /// assert_eq!(uc.into_inner(), 5); + /// ``` + #[inline] + #[unstable(feature = "unsafe_cell_raw_get", issue = "66358")] + pub const fn raw_get(this: *const Self) -> *mut T { + // We can just cast the pointer from `UnsafeCell` to `T` because of + // #[repr(transparent)]. This exploits libstd's special status, there is + // no guarantee for user code that this will work in future versions of the compiler! + this as *const T as *mut T + } } #[stable(feature = "unsafe_cell_default", since = "1.10.0")] diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index c456e14db1..dd21c72e74 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -158,7 +158,6 @@ impl From for char { } } - /// An error which can be returned when parsing a char. #[stable(feature = "char_from_str", since = "1.20.0")] #[derive(Clone, Debug, PartialEq, Eq)] @@ -167,16 +166,16 @@ pub struct ParseCharError { } impl ParseCharError { - #[unstable(feature = "char_error_internals", - reason = "this method should not be available publicly", - issue = "0")] + #[unstable( + feature = "char_error_internals", + reason = "this method should not be available publicly", + issue = "0" + )] #[doc(hidden)] pub fn __description(&self) -> &str { match self.kind { - CharErrorKind::EmptyString => { - "cannot parse char from empty string" - }, - CharErrorKind::TooManyChars => "too many characters in string" + CharErrorKind::EmptyString => "cannot parse char from empty string", + CharErrorKind::TooManyChars => "too many characters in string", } } } @@ -194,7 +193,6 @@ impl fmt::Display for ParseCharError { } } - #[stable(feature = "char_from_str", since = "1.20.0")] impl FromStr for char { type Err = ParseCharError; @@ -203,18 +201,13 @@ impl FromStr for char { fn from_str(s: &str) -> Result { let mut chars = s.chars(); match (chars.next(), chars.next()) { - (None, _) => { - Err(ParseCharError { kind: CharErrorKind::EmptyString }) - }, + (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }), (Some(c), None) => Ok(c), - _ => { - Err(ParseCharError { kind: CharErrorKind::TooManyChars }) - } + _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }), } } } - #[stable(feature = "try_from", since = "1.34.0")] impl TryFrom for char { type Error = CharTryFromError; @@ -224,6 +217,7 @@ impl TryFrom for char { if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { Err(CharTryFromError(())) } else { + // SAFETY: checked that it's a legal unicode value Ok(unsafe { from_u32_unchecked(i) }) } } @@ -303,11 +297,7 @@ pub fn from_digit(num: u32, radix: u32) -> Option { } if num < radix { let num = num as u8; - if num < 10 { - Some((b'0' + num) as char) - } else { - Some((b'a' + num - 10) as char) - } + if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) } } else { None } diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs index b71c9c2c40..5e7784730e 100644 --- a/src/libcore/char/decode.rs +++ b/src/libcore/char/decode.rs @@ -8,7 +8,8 @@ use super::from_u32_unchecked; #[stable(feature = "decode_utf16", since = "1.9.0")] #[derive(Clone, Debug)] pub struct DecodeUtf16 - where I: Iterator +where + I: Iterator, { iter: I, buf: Option, @@ -70,10 +71,7 @@ pub struct DecodeUtf16Error { #[stable(feature = "decode_utf16", since = "1.9.0")] #[inline] pub fn decode_utf16>(iter: I) -> DecodeUtf16 { - DecodeUtf16 { - iter: iter.into_iter(), - buf: None, - } + DecodeUtf16 { iter: iter.into_iter(), buf: None } } #[stable(feature = "decode_utf16", since = "1.9.0")] @@ -83,11 +81,11 @@ impl> Iterator for DecodeUtf16 { fn next(&mut self) -> Option> { let u = match self.buf.take() { Some(buf) => buf, - None => self.iter.next()? + None => self.iter.next()?, }; if u < 0xD800 || 0xDFFF < u { - // not a surrogate + // SAFETY: not a surrogate Some(Ok(unsafe { from_u32_unchecked(u as u32) })) } else if u >= 0xDC00 { // a trailing surrogate @@ -107,6 +105,7 @@ impl> Iterator for DecodeUtf16 { // all ok, so lets decode it. let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000; + // SAFETY: we checked that it's a legal unicode value Some(Ok(unsafe { from_u32_unchecked(c) })) } } diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index 971d89e004..5cfb9583a8 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -130,11 +130,7 @@ impl char { } }; - if val < radix { - Some(val) - } else { - None - } + if val < radix { Some(val) } else { None } } /// Returns an iterator that yields the hexadecimal Unicode escape of a @@ -438,6 +434,7 @@ impl char { #[inline] pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str { let code = self as u32; + // SAFETY: each arm checks the size of the slice and only uses `get_unchecked` unsafe ops unsafe { let len = if code < MAX_ONE_B && !dst.is_empty() { *dst.get_unchecked_mut(0) = code as u8; @@ -507,6 +504,7 @@ impl char { #[inline] pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { let mut code = self as u32; + // SAFETY: each arm checks whether there are enough bits to write into unsafe { if (code & 0xFFFF) == code && !dst.is_empty() { // The BMP falls through (assuming non-surrogate, as it should) @@ -555,8 +553,7 @@ impl char { pub fn is_alphabetic(self) -> bool { match self { 'a'..='z' | 'A'..='Z' => true, - c if c > '\x7f' => derived_property::Alphabetic(c), - _ => false, + c => c > '\x7f' && derived_property::Alphabetic(c), } } @@ -587,8 +584,7 @@ impl char { pub fn is_lowercase(self) -> bool { match self { 'a'..='z' => true, - c if c > '\x7f' => derived_property::Lowercase(c), - _ => false, + c => c > '\x7f' && derived_property::Lowercase(c), } } @@ -619,8 +615,7 @@ impl char { pub fn is_uppercase(self) -> bool { match self { 'A'..='Z' => true, - c if c > '\x7f' => derived_property::Uppercase(c), - _ => false, + c => c > '\x7f' && derived_property::Uppercase(c), } } @@ -648,8 +643,7 @@ impl char { pub fn is_whitespace(self) -> bool { match self { ' ' | '\x09'..='\x0d' => true, - c if c > '\x7f' => property::White_Space(c), - _ => false, + c => c > '\x7f' && property::White_Space(c), } } @@ -746,8 +740,7 @@ impl char { pub fn is_numeric(self) -> bool { match self { '0'..='9' => true, - c if c > '\x7f' => general_category::N(c), - _ => false, + c => c > '\x7f' && general_category::N(c), } } @@ -918,6 +911,10 @@ impl char { /// assert!(!non_ascii.is_ascii()); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.32.0"), + )] #[inline] pub const fn is_ascii(&self) -> bool { *self as u32 <= 0x7F @@ -948,11 +945,7 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> char { - if self.is_ascii() { - (*self as u8).to_ascii_uppercase() as char - } else { - *self - } + if self.is_ascii() { (*self as u8).to_ascii_uppercase() as char } else { *self } } /// Makes a copy of the value in its ASCII lower case equivalent. @@ -980,11 +973,7 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> char { - if self.is_ascii() { - (*self as u8).to_ascii_lowercase() as char - } else { - *self - } + if self.is_ascii() { (*self as u8).to_ascii_lowercase() as char } else { *self } } /// Checks that two values are an ASCII case-insensitive match. diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index dedd2f758b..a655ee6e7e 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -24,14 +24,14 @@ mod decode; mod methods; // stable re-exports -#[stable(feature = "rust1", since = "1.0.0")] -pub use self::convert::{from_u32, from_digit}; #[stable(feature = "char_from_unchecked", since = "1.5.0")] pub use self::convert::from_u32_unchecked; -#[stable(feature = "char_from_str", since = "1.20.0")] -pub use self::convert::ParseCharError; #[stable(feature = "try_from", since = "1.34.0")] pub use self::convert::CharTryFromError; +#[stable(feature = "char_from_str", since = "1.20.0")] +pub use self::convert::ParseCharError; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::convert::{from_digit, from_u32}; #[stable(feature = "decode_utf16", since = "1.9.0")] pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error}; @@ -45,13 +45,13 @@ use crate::fmt::{self, Write}; use crate::iter::FusedIterator; // UTF-8 ranges and tags for encoding characters -const TAG_CONT: u8 = 0b1000_0000; -const TAG_TWO_B: u8 = 0b1100_0000; -const TAG_THREE_B: u8 = 0b1110_0000; -const TAG_FOUR_B: u8 = 0b1111_0000; -const MAX_ONE_B: u32 = 0x80; -const MAX_TWO_B: u32 = 0x800; -const MAX_THREE_B: u32 = 0x10000; +const TAG_CONT: u8 = 0b1000_0000; +const TAG_TWO_B: u8 = 0b1100_0000; +const TAG_THREE_B: u8 = 0b1110_0000; +const TAG_FOUR_B: u8 = 0b1111_0000; +const MAX_ONE_B: u32 = 0x80; +const MAX_TWO_B: u32 = 0x800; +const MAX_THREE_B: u32 = 0x10000; /* Lu Uppercase_Letter an uppercase letter @@ -190,11 +190,11 @@ impl Iterator for EscapeUnicode { match self.state { EscapeUnicodeState::Done => None, - EscapeUnicodeState::RightBrace | - EscapeUnicodeState::Value | - EscapeUnicodeState::LeftBrace | - EscapeUnicodeState::Type | - EscapeUnicodeState::Backslash => Some('}'), + EscapeUnicodeState::RightBrace + | EscapeUnicodeState::Value + | EscapeUnicodeState::LeftBrace + | EscapeUnicodeState::Type + | EscapeUnicodeState::Backslash => Some('}'), } } } @@ -204,14 +204,15 @@ impl ExactSizeIterator for EscapeUnicode { #[inline] fn len(&self) -> usize { // The match is a single memory access with no branching - self.hex_digit_idx + match self.state { - EscapeUnicodeState::Done => 0, - EscapeUnicodeState::RightBrace => 1, - EscapeUnicodeState::Value => 2, - EscapeUnicodeState::LeftBrace => 3, - EscapeUnicodeState::Type => 4, - EscapeUnicodeState::Backslash => 5, - } + self.hex_digit_idx + + match self.state { + EscapeUnicodeState::Done => 0, + EscapeUnicodeState::RightBrace => 1, + EscapeUnicodeState::Value => 2, + EscapeUnicodeState::LeftBrace => 3, + EscapeUnicodeState::Type => 4, + EscapeUnicodeState::Backslash => 5, + } } } @@ -238,7 +239,7 @@ impl fmt::Display for EscapeUnicode { #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct EscapeDefault { - state: EscapeDefaultState + state: EscapeDefaultState, } #[derive(Clone, Debug)] @@ -284,24 +285,20 @@ impl Iterator for EscapeDefault { EscapeDefaultState::Backslash(c) if n == 0 => { self.state = EscapeDefaultState::Char(c); Some('\\') - }, + } EscapeDefaultState::Backslash(c) if n == 1 => { self.state = EscapeDefaultState::Done; Some(c) - }, + } EscapeDefaultState::Backslash(_) => { self.state = EscapeDefaultState::Done; None - }, + } EscapeDefaultState::Char(c) => { self.state = EscapeDefaultState::Done; - if n == 0 { - Some(c) - } else { - None - } - }, + if n == 0 { Some(c) } else { None } + } EscapeDefaultState::Done => None, EscapeDefaultState::Unicode(ref mut i) => i.nth(n), } @@ -355,12 +352,16 @@ pub struct EscapeDebug(EscapeDefault); #[stable(feature = "char_escape_debug", since = "1.20.0")] impl Iterator for EscapeDebug { type Item = char; - fn next(&mut self) -> Option { self.0.next() } - fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + fn next(&mut self) -> Option { + self.0.next() + } + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } } #[stable(feature = "char_escape_debug", since = "1.20.0")] -impl ExactSizeIterator for EscapeDebug { } +impl ExactSizeIterator for EscapeDebug {} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDebug {} @@ -440,7 +441,7 @@ impl CaseMappingIter { fn new(chars: [char; 3]) -> CaseMappingIter { if chars[2] == '\0' { if chars[1] == '\0' { - CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0' + CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0' } else { CaseMappingIter::Two(chars[0], chars[1]) } @@ -493,9 +494,7 @@ impl fmt::Display for CaseMappingIter { f.write_char(b)?; f.write_char(c) } - CaseMappingIter::One(c) => { - f.write_char(c) - } + CaseMappingIter::One(c) => f.write_char(c), CaseMappingIter::Zero => Ok(()), } } diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 14d947ccf2..18f808638d 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -107,7 +107,7 @@ /// [impls]: #implementors #[stable(feature = "rust1", since = "1.0.0")] #[lang = "clone"] -pub trait Clone : Sized { +pub trait Clone: Sized { /// Returns a copy of the value. /// /// # Examples @@ -137,7 +137,9 @@ pub trait Clone : Sized { #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] -pub macro Clone($item:item) { /* compiler built-in */ } +pub macro Clone($item:item) { + /* compiler built-in */ +} // FIXME(aburka): these structs are used solely by #[derive] to // assert that every component of a type implements Clone or Copy. @@ -145,16 +147,24 @@ pub macro Clone($item:item) { /* compiler built-in */ } // These structs should never appear in user code. #[doc(hidden)] #[allow(missing_debug_implementations)] -#[unstable(feature = "derive_clone_copy", - reason = "deriving hack, should not be public", - issue = "0")] -pub struct AssertParamIsClone { _field: crate::marker::PhantomData } +#[unstable( + feature = "derive_clone_copy", + reason = "deriving hack, should not be public", + issue = "0" +)] +pub struct AssertParamIsClone { + _field: crate::marker::PhantomData, +} #[doc(hidden)] #[allow(missing_debug_implementations)] -#[unstable(feature = "derive_clone_copy", - reason = "deriving hack, should not be public", - issue = "0")] -pub struct AssertParamIsCopy { _field: crate::marker::PhantomData } +#[unstable( + feature = "derive_clone_copy", + reason = "deriving hack, should not be public", + issue = "0" +)] +pub struct AssertParamIsCopy { + _field: crate::marker::PhantomData, +} /// Implementations of `Clone` for primitive types. /// @@ -217,5 +227,4 @@ mod impls { *self } } - } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 1ac51291b9..4aa52a7a39 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -135,10 +135,15 @@ use self::Ordering::*; /// By changing `impl PartialEq for Book` to `impl PartialEq for Book`, /// we allow `BookFormat`s to be compared with `Book`s. /// -/// You can also combine these implementations to let the `==` operator work with -/// two different types: -/// -/// ``` +/// A comparison like the one above, which ignores some fields of the struct, +/// can be dangerous. It can easily lead to an unintended violation of the +/// requirements for a partial equivalence relation. For example, if we kept +/// the above implementation of `PartialEq` for `BookFormat` and added an +/// implementation of `PartialEq` for `Book` (either via a `#[derive]` or +/// via the manual implementation from the first example) then the result would +/// violate transitivity: +/// +/// ```should_panic /// #[derive(PartialEq)] /// enum BookFormat { /// Paperback, @@ -146,6 +151,7 @@ use self::Ordering::*; /// Ebook, /// } /// +/// #[derive(PartialEq)] /// struct Book { /// isbn: i32, /// format: BookFormat, @@ -163,18 +169,16 @@ use self::Ordering::*; /// } /// } /// -/// impl PartialEq for Book { -/// fn eq(&self, other: &Book) -> bool { -/// self.isbn == other.isbn -/// } -/// } +/// fn main() { +/// let b1 = Book { isbn: 1, format: BookFormat::Paperback }; +/// let b2 = Book { isbn: 2, format: BookFormat::Paperback }; /// -/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; -/// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; +/// assert!(b1 == BookFormat::Paperback); +/// assert!(BookFormat::Paperback == b2); /// -/// assert!(b1 == BookFormat::Paperback); -/// assert!(BookFormat::Ebook != b1); -/// assert!(b1 == b2); +/// // The following should hold by transitivity but doesn't. +/// assert!(b1 == b2); // <-- PANICS +/// } /// ``` /// /// # Examples @@ -460,9 +464,9 @@ impl PartialOrd for Reverse { #[inline] fn le(&self, other: &Self) -> bool { other.0 <= self.0 } #[inline] - fn ge(&self, other: &Self) -> bool { other.0 >= self.0 } - #[inline] fn gt(&self, other: &Self) -> bool { other.0 > self.0 } + #[inline] + fn ge(&self, other: &Self) -> bool { other.0 >= self.0 } } #[stable(feature = "reverse_cmp_key", since = "1.19.0")] @@ -530,7 +534,6 @@ impl Ord for Reverse { /// } /// } /// ``` -#[lang = "ord"] #[doc(alias = "<")] #[doc(alias = ">")] #[doc(alias = "<=")] @@ -1002,6 +1005,7 @@ pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types mod impls { + use crate::hint::unreachable_unchecked; use crate::cmp::Ordering::{self, Less, Greater, Equal}; macro_rules! partial_eq_impl { @@ -1122,7 +1126,16 @@ mod impls { impl Ord for bool { #[inline] fn cmp(&self, other: &bool) -> Ordering { - (*self as u8).cmp(&(*other as u8)) + // Casting to i8's and converting the difference to an Ordering generates + // more optimal assembly. + // See for more info. + match (*self as i8) - (*other as i8) { + -1 => Less, + 0 => Equal, + 1 => Greater, + // SAFETY: bool as i8 returns 0 or 1, so the difference can't be anything else + _ => unsafe { unreachable_unchecked() }, + } } } @@ -1172,9 +1185,9 @@ mod impls { #[inline] fn le(&self, other: & &B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) } - #[inline] fn gt(&self, other: & &B) -> bool { PartialOrd::gt(*self, *other) } + #[inline] + fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &A where A: Ord { @@ -1204,9 +1217,9 @@ mod impls { #[inline] fn le(&self, other: &&mut B) -> bool { PartialOrd::le(*self, *other) } #[inline] - fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) } - #[inline] fn gt(&self, other: &&mut B) -> bool { PartialOrd::gt(*self, *other) } + #[inline] + fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &mut A where A: Ord { diff --git a/src/libcore/convert.rs b/src/libcore/convert/mod.rs similarity index 92% rename from src/libcore/convert.rs rename to src/libcore/convert/mod.rs index 3cd2337ee5..e5599f1dd3 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert/mod.rs @@ -42,6 +42,11 @@ use crate::fmt; +mod num; + +#[unstable(feature = "convert_float_to_int", issue = "67057")] +pub use num::FloatToInt; + /// The identity function. /// /// Two things are important to note about this function: @@ -96,8 +101,11 @@ use crate::fmt; /// assert_eq!(vec![1, 3], filtered); /// ``` #[stable(feature = "convert_id", since = "1.33.0")] +#[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_identity", since = "1.33.0"))] #[inline] -pub const fn identity(x: T) -> T { x } +pub const fn identity(x: T) -> T { + x +} /// Used to do a cheap reference-to-reference conversion. /// @@ -205,11 +213,12 @@ pub trait AsMut { /// A value-to-value conversion that consumes the input value. The /// opposite of [`From`]. /// -/// One should only implement [`Into`] if a conversion to a type outside the current crate is -/// required. Otherwise one should always prefer implementing [`From`] over [`Into`] because -/// implementing [`From`] automatically provides one with a implementation of [`Into`] thanks to -/// the blanket implementation in the standard library. [`From`] cannot do these type of -/// conversions because of Rust's orphaning rules. +/// One should avoid implementing [`Into`] and implement [`From`] instead. +/// Implementing [`From`] automatically provides one with an implementation of [`Into`] +/// thanks to the blanket implementation in the standard library. +/// +/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function +/// to ensure that types that only implement [`Into`] can be used as well. /// /// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`]. /// @@ -218,13 +227,13 @@ pub trait AsMut { /// - [`From`]` for U` implies `Into for T` /// - [`Into`] is reflexive, which means that `Into for T` is implemented /// -/// # Implementing [`Into`] for conversions to external types +/// # Implementing [`Into`] for conversions to external types in old versions of Rust /// -/// If the destination type is not part of the current crate -/// then you can't implement [`From`] directly. +/// Prior to Rust 1.40, if the destination type was not part of the current crate +/// then you couldn't implement [`From`] directly. /// For example, take this code: /// -/// ```compile_fail +/// ``` /// struct Wrapper(Vec); /// impl From> for Vec { /// fn from(w: Wrapper) -> Vec { @@ -232,9 +241,8 @@ pub trait AsMut { /// } /// } /// ``` -/// This will fail to compile because we cannot implement a trait for a type -/// if both the trait and the type are not defined by the current crate. -/// This is due to Rust's orphaning rules. To bypass this, you can implement [`Into`] directly: +/// This will fail to compile in older versions of the language because Rust's orphaning rules +/// used to be a little bit more strict. To bypass this, you could implement [`Into`] directly: /// /// ``` /// struct Wrapper(Vec); @@ -249,9 +257,6 @@ pub trait AsMut { /// (as [`From`] does with [`Into`]). Therefore, you should always try to implement [`From`] /// and then fall back to [`Into`] if [`From`] can't be implemented. /// -/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function -/// to ensure that types that only implement [`Into`] can be used as well. -/// /// # Examples /// /// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`: @@ -289,7 +294,7 @@ pub trait Into: Sized { /// [`Into`]. /// /// One should always prefer implementing `From` over [`Into`] -/// because implementing `From` automatically provides one with a implementation of [`Into`] +/// because implementing `From` automatically provides one with an implementation of [`Into`] /// thanks to the blanket implementation in the standard library. /// /// Only implement [`Into`] if a conversion to a type outside the current crate is required. @@ -369,12 +374,10 @@ pub trait Into: Sized { /// [`from`]: trait.From.html#tymethod.from /// [book]: ../../book/ch09-00-error-handling.html #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - on( - all(_Self="&str", T="std::string::String"), - note="to coerce a `{T}` into a `{Self}`, use `&*` as a prefix", - ) -)] +#[rustc_on_unimplemented(on( + all(_Self = "&str", T = "std::string::String"), + note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix", +))] pub trait From: Sized { /// Performs the conversion. #[stable(feature = "rust1", since = "1.0.0")] @@ -438,16 +441,16 @@ pub trait TryInto: Sized { /// ``` /// use std::convert::TryFrom; /// -/// struct SuperiorThanZero(i32); +/// struct GreaterThanZero(i32); /// -/// impl TryFrom for SuperiorThanZero { +/// impl TryFrom for GreaterThanZero { /// type Error = &'static str; /// /// fn try_from(value: i32) -> Result { -/// if value < 0 { -/// Err("SuperiorThanZero only accepts value superior than zero!") +/// if value <= 0 { +/// Err("GreaterThanZero only accepts value superior than zero!") /// } else { -/// Ok(SuperiorThanZero(value)) +/// Ok(GreaterThanZero(value)) /// } /// } /// } @@ -498,7 +501,9 @@ pub trait TryFrom: Sized { // As lifts over & #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef for &T where T: AsRef +impl AsRef for &T +where + T: AsRef, { fn as_ref(&self) -> &U { >::as_ref(*self) @@ -507,7 +512,9 @@ impl AsRef for &T where T: AsRef // As lifts over &mut #[stable(feature = "rust1", since = "1.0.0")] -impl AsRef for &mut T where T: AsRef +impl AsRef for &mut T +where + T: AsRef, { fn as_ref(&self) -> &U { >::as_ref(*self) @@ -524,7 +531,9 @@ impl AsRef for &mut T where T: AsRef // AsMut lifts over &mut #[stable(feature = "rust1", since = "1.0.0")] -impl AsMut for &mut T where T: AsMut +impl AsMut for &mut T +where + T: AsMut, { fn as_mut(&mut self) -> &mut U { (*self).as_mut() @@ -541,7 +550,9 @@ impl AsMut for &mut T where T: AsMut // From implies Into #[stable(feature = "rust1", since = "1.0.0")] -impl Into for T where U: From +impl Into for T +where + U: From, { fn into(self) -> U { U::from(self) @@ -551,7 +562,9 @@ impl Into for T where U: From // From (and thus Into) is reflexive #[stable(feature = "rust1", since = "1.0.0")] impl From for T { - fn from(t: T) -> T { t } + fn from(t: T) -> T { + t + } } /// **Stability note:** This impl does not yet exist, but we are @@ -560,16 +573,20 @@ impl From for T { /// /// [#64715]: https://github.com/rust-lang/rust/issues/64715 #[stable(feature = "convert_infallible", since = "1.34.0")] -#[cfg(not(bootstrap))] -#[rustc_reservation_impl="permitting this impl would forbid us from adding \ -`impl From for T` later; see rust-lang/rust#64715 for details"] +#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead. +#[rustc_reservation_impl = "permitting this impl would forbid us from adding \ + `impl From for T` later; see rust-lang/rust#64715 for details"] impl From for T { - fn from(t: !) -> T { t } + fn from(t: !) -> T { + t + } } // TryFrom implies TryInto #[stable(feature = "try_from", since = "1.34.0")] -impl TryInto for T where U: TryFrom +impl TryInto for T +where + U: TryFrom, { type Error = U::Error; @@ -581,7 +598,10 @@ impl TryInto for T where U: TryFrom // Infallible conversions are semantically equivalent to fallible conversions // with an uninhabited error type. #[stable(feature = "try_from", since = "1.34.0")] -impl TryFrom for T where U: Into { +impl TryFrom for T +where + U: Into, +{ type Error = Infallible; fn try_from(value: U) -> Result { diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs new file mode 100644 index 0000000000..6f5ee756f5 --- /dev/null +++ b/src/libcore/convert/num.rs @@ -0,0 +1,449 @@ +use super::{From, TryFrom}; +use crate::num::TryFromIntError; + +mod private { + /// This trait being unreachable from outside the crate + /// prevents other implementations of the `FloatToInt` trait, + /// which allows potentially adding more trait methods after the trait is `#[stable]`. + #[unstable(feature = "convert_float_to_int", issue = "67057")] + pub trait Sealed {} +} + +/// Supporting trait for inherent methods of `f32` and `f64` such as `round_unchecked_to`. +/// Typically doesn’t need to be used directly. +#[unstable(feature = "convert_float_to_int", issue = "67057")] +pub trait FloatToInt: private::Sealed + Sized { + #[cfg(not(bootstrap))] + #[unstable(feature = "float_approx_unchecked_to", issue = "67058")] + #[doc(hidden)] + unsafe fn approx_unchecked(self) -> Int; +} + +macro_rules! impl_float_to_int { + ( $Float: ident => $( $Int: ident )+ ) => { + #[unstable(feature = "convert_float_to_int", issue = "67057")] + impl private::Sealed for $Float {} + $( + #[unstable(feature = "convert_float_to_int", issue = "67057")] + impl FloatToInt<$Int> for $Float { + #[cfg(not(bootstrap))] + #[doc(hidden)] + #[inline] + unsafe fn approx_unchecked(self) -> $Int { + crate::intrinsics::float_to_int_approx_unchecked(self) + } + } + )+ + } +} + +impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize); +impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize); + +// Conversion traits for primitive integer and float types +// Conversions T -> T are covered by a blanket impl and therefore excluded +// Some conversions from and to usize/isize are not implemented due to portability concerns +macro_rules! impl_from { + ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { + #[$attr] + #[doc = $doc] + impl From<$Small> for $Large { + #[inline] + fn from(small: $Small) -> $Large { + small as $Large + } + } + }; + ($Small: ty, $Large: ty, #[$attr:meta]) => { + impl_from!($Small, + $Large, + #[$attr], + concat!("Converts `", + stringify!($Small), + "` to `", + stringify!($Large), + "` losslessly.")); + } +} + +macro_rules! impl_from_bool { + ($target: ty, #[$attr:meta]) => { + impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `", + stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true` +values. + +# Examples + +``` +assert_eq!(", stringify!($target), "::from(true), 1); +assert_eq!(", stringify!($target), "::from(false), 0); +```")); + }; +} + +// Bool -> Any +impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] } +impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] } + +// Unsigned -> Unsigned +impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] } + +// Signed -> Signed +impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] } + +// Unsigned -> Signed +impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } +impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] } +impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] } + +// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX +// which imply that pointer-sized integers must be at least 16 bits: +// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4 +impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } +impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } +impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } + +// RISC-V defines the possibility of a 128-bit address space (RV128). + +// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize. +// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf +// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf + +// Note: integers can only be represented with full precision in a float if +// they fit in the significand, which is 24 bits in f32 and 53 bits in f64. +// Lossy float conversions are not implemented at this time. + +// Signed -> Float +impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } + +// Unsigned -> Float +impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } +impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } + +// Float -> Float +impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } + +// no possible bounds violation +macro_rules! try_from_unbounded { + ($source:ty, $($target:ty),*) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(value: $source) -> Result { + Ok(value as $target) + } + } + )*} +} + +// only negative bounds +macro_rules! try_from_lower_bounded { + ($source:ty, $($target:ty),*) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(u: $source) -> Result<$target, TryFromIntError> { + if u >= 0 { + Ok(u as $target) + } else { + Err(TryFromIntError(())) + } + } + } + )*} +} + +// unsigned to signed (only positive bound) +macro_rules! try_from_upper_bounded { + ($source:ty, $($target:ty),*) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(u: $source) -> Result<$target, TryFromIntError> { + if u > (<$target>::max_value() as $source) { + Err(TryFromIntError(())) + } else { + Ok(u as $target) + } + } + } + )*} +} + +// all other cases +macro_rules! try_from_both_bounded { + ($source:ty, $($target:ty),*) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + /// Try to create the target number type from a source + /// number type. This returns an error if the source value + /// is outside of the range of the target type. + #[inline] + fn try_from(u: $source) -> Result<$target, TryFromIntError> { + let min = <$target>::min_value() as $source; + let max = <$target>::max_value() as $source; + if u < min || u > max { + Err(TryFromIntError(())) + } else { + Ok(u as $target) + } + } + } + )*} +} + +macro_rules! rev { + ($mac:ident, $source:ty, $($target:ty),*) => {$( + $mac!($target, $source); + )*} +} + +// intra-sign conversions +try_from_upper_bounded!(u16, u8); +try_from_upper_bounded!(u32, u16, u8); +try_from_upper_bounded!(u64, u32, u16, u8); +try_from_upper_bounded!(u128, u64, u32, u16, u8); + +try_from_both_bounded!(i16, i8); +try_from_both_bounded!(i32, i16, i8); +try_from_both_bounded!(i64, i32, i16, i8); +try_from_both_bounded!(i128, i64, i32, i16, i8); + +// unsigned-to-signed +try_from_upper_bounded!(u8, i8); +try_from_upper_bounded!(u16, i8, i16); +try_from_upper_bounded!(u32, i8, i16, i32); +try_from_upper_bounded!(u64, i8, i16, i32, i64); +try_from_upper_bounded!(u128, i8, i16, i32, i64, i128); + +// signed-to-unsigned +try_from_lower_bounded!(i8, u8, u16, u32, u64, u128); +try_from_lower_bounded!(i16, u16, u32, u64, u128); +try_from_lower_bounded!(i32, u32, u64, u128); +try_from_lower_bounded!(i64, u64, u128); +try_from_lower_bounded!(i128, u128); +try_from_both_bounded!(i16, u8); +try_from_both_bounded!(i32, u16, u8); +try_from_both_bounded!(i64, u32, u16, u8); +try_from_both_bounded!(i128, u64, u32, u16, u8); + +// usize/isize +try_from_upper_bounded!(usize, isize); +try_from_lower_bounded!(isize, usize); + +#[cfg(target_pointer_width = "16")] +mod ptr_try_from_impls { + use super::TryFromIntError; + use crate::convert::TryFrom; + + try_from_upper_bounded!(usize, u8); + try_from_unbounded!(usize, u16, u32, u64, u128); + try_from_upper_bounded!(usize, i8, i16); + try_from_unbounded!(usize, i32, i64, i128); + + try_from_both_bounded!(isize, u8); + try_from_lower_bounded!(isize, u16, u32, u64, u128); + try_from_both_bounded!(isize, i8); + try_from_unbounded!(isize, i16, i32, i64, i128); + + rev!(try_from_upper_bounded, usize, u32, u64, u128); + rev!(try_from_lower_bounded, usize, i8, i16); + rev!(try_from_both_bounded, usize, i32, i64, i128); + + rev!(try_from_upper_bounded, isize, u16, u32, u64, u128); + rev!(try_from_both_bounded, isize, i32, i64, i128); +} + +#[cfg(target_pointer_width = "32")] +mod ptr_try_from_impls { + use super::TryFromIntError; + use crate::convert::TryFrom; + + try_from_upper_bounded!(usize, u8, u16); + try_from_unbounded!(usize, u32, u64, u128); + try_from_upper_bounded!(usize, i8, i16, i32); + try_from_unbounded!(usize, i64, i128); + + try_from_both_bounded!(isize, u8, u16); + try_from_lower_bounded!(isize, u32, u64, u128); + try_from_both_bounded!(isize, i8, i16); + try_from_unbounded!(isize, i32, i64, i128); + + rev!(try_from_unbounded, usize, u32); + rev!(try_from_upper_bounded, usize, u64, u128); + rev!(try_from_lower_bounded, usize, i8, i16, i32); + rev!(try_from_both_bounded, usize, i64, i128); + + rev!(try_from_unbounded, isize, u16); + rev!(try_from_upper_bounded, isize, u32, u64, u128); + rev!(try_from_unbounded, isize, i32); + rev!(try_from_both_bounded, isize, i64, i128); +} + +#[cfg(target_pointer_width = "64")] +mod ptr_try_from_impls { + use super::TryFromIntError; + use crate::convert::TryFrom; + + try_from_upper_bounded!(usize, u8, u16, u32); + try_from_unbounded!(usize, u64, u128); + try_from_upper_bounded!(usize, i8, i16, i32, i64); + try_from_unbounded!(usize, i128); + + try_from_both_bounded!(isize, u8, u16, u32); + try_from_lower_bounded!(isize, u64, u128); + try_from_both_bounded!(isize, i8, i16, i32); + try_from_unbounded!(isize, i64, i128); + + rev!(try_from_unbounded, usize, u32, u64); + rev!(try_from_upper_bounded, usize, u128); + rev!(try_from_lower_bounded, usize, i8, i16, i32, i64); + rev!(try_from_both_bounded, usize, i128); + + rev!(try_from_unbounded, isize, u16, u32); + rev!(try_from_upper_bounded, isize, u64, u128); + rev!(try_from_unbounded, isize, i32, i64); + rev!(try_from_both_bounded, isize, i128); +} + +// Conversion traits for non-zero integer types +use crate::num::NonZeroI128; +use crate::num::NonZeroI16; +use crate::num::NonZeroI32; +use crate::num::NonZeroI64; +use crate::num::NonZeroI8; +use crate::num::NonZeroIsize; +use crate::num::NonZeroU128; +use crate::num::NonZeroU16; +use crate::num::NonZeroU32; +use crate::num::NonZeroU64; +use crate::num::NonZeroU8; +use crate::num::NonZeroUsize; + +macro_rules! nzint_impl_from { + ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { + #[$attr] + #[doc = $doc] + impl From<$Small> for $Large { + #[inline] + fn from(small: $Small) -> $Large { + // SAFETY: input type guarantees the value is non-zero + unsafe { + <$Large>::new_unchecked(small.get().into()) + } + } + } + }; + ($Small: ty, $Large: ty, #[$attr:meta]) => { + nzint_impl_from!($Small, + $Large, + #[$attr], + concat!("Converts `", + stringify!($Small), + "` to `", + stringify!($Large), + "` losslessly.")); + } +} + +// Non-zero Unsigned -> Non-zero Unsigned +nzint_impl_from! { NonZeroU8, NonZeroU16, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU16, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU16, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU16, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU16, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU32, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU32, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU64, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } + +// Non-zero Signed -> Non-zero Signed +nzint_impl_from! { NonZeroI8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI16, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroI64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } + +// NonZero UnSigned -> Non-zero Signed +nzint_impl_from! { NonZeroU8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } +nzint_impl_from! { NonZeroU64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 1aadc77cfb..15ac3aea8b 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -119,7 +119,9 @@ pub trait Default: Sized { #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] -pub macro Default($item:item) { /* compiler built-in */ } +pub macro Default($item:item) { + /* compiler built-in */ +} macro_rules! default_impl { ($t:ty, $v:expr, $doc:tt) => { diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 569c667ac0..74ec24939a 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -1,5 +1,4 @@ #![stable(feature = "", since = "1.30.0")] - #![allow(non_camel_case_types)] //! Utilities related to FFI bindings. @@ -36,12 +35,20 @@ use crate::ops::{Deref, DerefMut}; #[repr(u8)] #[stable(feature = "core_c_void", since = "1.30.0")] pub enum c_void { - #[unstable(feature = "c_void_variant", reason = "temporary implementation detail", - issue = "0")] - #[doc(hidden)] __variant1, - #[unstable(feature = "c_void_variant", reason = "temporary implementation detail", - issue = "0")] - #[doc(hidden)] __variant2, + #[unstable( + feature = "c_void_variant", + reason = "temporary implementation detail", + issue = "0" + )] + #[doc(hidden)] + __variant1, + #[unstable( + feature = "c_void_variant", + reason = "temporary implementation detail", + issue = "0" + )] + #[doc(hidden)] + __variant2, } #[stable(feature = "std_debug", since = "1.16.0")] @@ -53,17 +60,20 @@ impl fmt::Debug for c_void { /// Basic implementation of a `va_list`. // The name is WIP, using `VaListImpl` for now. -#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), - all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", - windows))] +#[cfg(any( + all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), + all(target_arch = "aarch64", target_os = "ios"), + target_arch = "wasm32", + target_arch = "asmjs", + windows +))] #[repr(transparent)] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] #[lang = "va_list"] pub struct VaListImpl<'f> { ptr: *mut c_void, @@ -73,16 +83,19 @@ pub struct VaListImpl<'f> { _marker: PhantomData<&'f mut &'f c_void>, } -#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), - all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", - windows))] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[cfg(any( + all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), + all(target_arch = "aarch64", target_os = "ios"), + target_arch = "wasm32", + target_arch = "asmjs", + windows +))] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'f> fmt::Debug for VaListImpl<'f> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "va_list* {:p}", self.ptr) @@ -97,10 +110,12 @@ impl<'f> fmt::Debug for VaListImpl<'f> { #[cfg(all(target_arch = "aarch64", not(target_os = "ios"), not(windows)))] #[repr(C)] #[derive(Debug)] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] #[lang = "va_list"] pub struct VaListImpl<'f> { stack: *mut c_void, @@ -115,10 +130,12 @@ pub struct VaListImpl<'f> { #[cfg(all(target_arch = "powerpc", not(windows)))] #[repr(C)] #[derive(Debug)] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] #[lang = "va_list"] pub struct VaListImpl<'f> { gpr: u8, @@ -133,10 +150,12 @@ pub struct VaListImpl<'f> { #[cfg(all(target_arch = "x86_64", not(windows)))] #[repr(C)] #[derive(Debug)] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] #[lang = "va_list"] pub struct VaListImpl<'f> { gp_offset: i32, @@ -149,76 +168,86 @@ pub struct VaListImpl<'f> { /// A wrapper for a `va_list` #[repr(transparent)] #[derive(Debug)] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] pub struct VaList<'a, 'f: 'a> { - #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), - all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", - windows))] + #[cfg(any( + all( + not(target_arch = "aarch64"), + not(target_arch = "powerpc"), + not(target_arch = "x86_64") + ), + all(target_arch = "aarch64", target_os = "ios"), + target_arch = "wasm32", + target_arch = "asmjs", + windows + ))] inner: VaListImpl<'f>, - #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", - target_arch = "x86_64"), - any(not(target_arch = "aarch64"), not(target_os = "ios")), - not(target_arch = "wasm32"), - not(target_arch = "asmjs"), - not(windows)))] + #[cfg(all( + any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), + any(not(target_arch = "aarch64"), not(target_os = "ios")), + not(target_arch = "wasm32"), + not(target_arch = "asmjs"), + not(windows) + ))] inner: &'a mut VaListImpl<'f>, _marker: PhantomData<&'a mut VaListImpl<'f>>, } -#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), - all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", - windows))] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[cfg(any( + all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), + all(target_arch = "aarch64", target_os = "ios"), + target_arch = "wasm32", + target_arch = "asmjs", + windows +))] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'f> VaListImpl<'f> { /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. #[inline] pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { - inner: VaListImpl { ..*self }, - _marker: PhantomData, - } + VaList { inner: VaListImpl { ..*self }, _marker: PhantomData } } } -#[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", - target_arch = "x86_64"), - any(not(target_arch = "aarch64"), not(target_os = "ios")), - not(target_arch = "wasm32"), - not(target_arch = "asmjs"), - not(windows)))] -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[cfg(all( + any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), + any(not(target_arch = "aarch64"), not(target_os = "ios")), + not(target_arch = "wasm32"), + not(target_arch = "asmjs"), + not(windows) +))] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'f> VaListImpl<'f> { /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`. #[inline] pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { - VaList { - inner: self, - _marker: PhantomData, - } + VaList { inner: self, _marker: PhantomData } } } -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'a, 'f: 'a> Deref for VaList<'a, 'f> { type Target = VaListImpl<'f>; @@ -228,10 +257,12 @@ impl<'a, 'f: 'a> Deref for VaList<'a, 'f> { } } -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> { #[inline] fn deref_mut(&mut self) -> &mut VaListImpl<'f> { @@ -252,10 +283,12 @@ mod sealed_trait { /// Trait which whitelists the allowed types to be used with [VaList::arg] /// /// [VaList::va_arg]: struct.VaList.html#method.arg - #[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] + #[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" + )] pub trait VaArgSafe {} } @@ -271,25 +304,31 @@ macro_rules! impl_va_arg_safe { } } -impl_va_arg_safe!{i8, i16, i32, i64, usize} -impl_va_arg_safe!{u8, u16, u32, u64, isize} -impl_va_arg_safe!{f64} +impl_va_arg_safe! {i8, i16, i32, i64, usize} +impl_va_arg_safe! {u8, u16, u32, u64, isize} +impl_va_arg_safe! {f64} -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl sealed_trait::VaArgSafe for *mut T {} -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl sealed_trait::VaArgSafe for *const T {} -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'f> VaListImpl<'f> { /// Advance to the next arg. #[inline] @@ -299,7 +338,9 @@ impl<'f> VaListImpl<'f> { /// Copies the `va_list` at the current location. pub unsafe fn with_copy(&self, f: F) -> R - where F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R { + where + F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R, + { let mut ap = self.clone(); let ret = f(ap.as_va_list()); va_end(&mut ap); @@ -307,14 +348,17 @@ impl<'f> VaListImpl<'f> { } } -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'f> Clone for VaListImpl<'f> { #[inline] fn clone(&self) -> Self { let mut dest = crate::mem::MaybeUninit::uninit(); + // SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal unsafe { va_copy(dest.as_mut_ptr(), self); dest.assume_init() @@ -322,10 +366,12 @@ impl<'f> Clone for VaListImpl<'f> { } } -#[unstable(feature = "c_variadic", - reason = "the `c_variadic` feature has not been properly tested on \ - all supported platforms", - issue = "44930")] +#[unstable( + feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930" +)] impl<'f> Drop for VaListImpl<'f> { fn drop(&mut self) { // FIXME: this should call `va_end`, but there's no clean way to diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index a2fff913ac..284e94926d 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -1,13 +1,20 @@ -use crate::fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug}; +use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp}; use crate::mem::MaybeUninit; use crate::num::flt2dec; +// ignore-tidy-undocumented-unsafe + // Don't inline this so callers don't use the stack space this function // requires unless they have to. #[inline(never)] -fn float_to_decimal_common_exact(fmt: &mut Formatter<'_>, num: &T, - sign: flt2dec::Sign, precision: usize) -> Result - where T: flt2dec::DecodableFloat +fn float_to_decimal_common_exact( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + precision: usize, +) -> Result +where + T: flt2dec::DecodableFloat, { unsafe { let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64 @@ -17,9 +24,15 @@ fn float_to_decimal_common_exact(fmt: &mut Formatter<'_>, num: &T, // we decided whether that is valid or not. // We can do this only because we are libstd and coupled to the compiler. // (FWIW, using `freeze` would not be enough; `flt2dec::Part` is an enum!) - let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact, - *num, sign, precision, - false, buf.get_mut(), parts.get_mut()); + let formatted = flt2dec::to_exact_fixed_str( + flt2dec::strategy::grisu::format_exact, + *num, + sign, + precision, + false, + buf.get_mut(), + parts.get_mut(), + ); fmt.pad_formatted_parts(&formatted) } } @@ -27,33 +40,49 @@ fn float_to_decimal_common_exact(fmt: &mut Formatter<'_>, num: &T, // Don't inline this so callers that call both this and the above won't wind // up using the combined stack space of both functions in some cases. #[inline(never)] -fn float_to_decimal_common_shortest(fmt: &mut Formatter<'_>, num: &T, - sign: flt2dec::Sign, precision: usize) -> Result - where T: flt2dec::DecodableFloat +fn float_to_decimal_common_shortest( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + precision: usize, +) -> Result +where + T: flt2dec::DecodableFloat, { unsafe { // enough for f32 and f64 let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit(); let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 4]>::uninit(); // FIXME(#53491) - let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num, - sign, precision, false, buf.get_mut(), - parts.get_mut()); + let formatted = flt2dec::to_shortest_str( + flt2dec::strategy::grisu::format_shortest, + *num, + sign, + precision, + false, + buf.get_mut(), + parts.get_mut(), + ); fmt.pad_formatted_parts(&formatted) } } // Common code of floating point Debug and Display. -fn float_to_decimal_common(fmt: &mut Formatter<'_>, num: &T, - negative_zero: bool, min_precision: usize) -> Result - where T: flt2dec::DecodableFloat +fn float_to_decimal_common( + fmt: &mut Formatter<'_>, + num: &T, + negative_zero: bool, + min_precision: usize, +) -> Result +where + T: flt2dec::DecodableFloat, { let force_sign = fmt.sign_plus(); let sign = match (force_sign, negative_zero) { (false, false) => flt2dec::Sign::Minus, - (false, true) => flt2dec::Sign::MinusRaw, - (true, false) => flt2dec::Sign::MinusPlus, - (true, true) => flt2dec::Sign::MinusPlusRaw, + (false, true) => flt2dec::Sign::MinusRaw, + (true, false) => flt2dec::Sign::MinusPlus, + (true, true) => flt2dec::Sign::MinusPlusRaw, }; if let Some(precision) = fmt.precision { @@ -66,18 +95,29 @@ fn float_to_decimal_common(fmt: &mut Formatter<'_>, num: &T, // Don't inline this so callers don't use the stack space this function // requires unless they have to. #[inline(never)] -fn float_to_exponential_common_exact(fmt: &mut Formatter<'_>, num: &T, - sign: flt2dec::Sign, precision: usize, - upper: bool) -> Result - where T: flt2dec::DecodableFloat +fn float_to_exponential_common_exact( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + precision: usize, + upper: bool, +) -> Result +where + T: flt2dec::DecodableFloat, { unsafe { let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64 let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit(); // FIXME(#53491) - let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact, - *num, sign, precision, - upper, buf.get_mut(), parts.get_mut()); + let formatted = flt2dec::to_exact_exp_str( + flt2dec::strategy::grisu::format_exact, + *num, + sign, + precision, + upper, + buf.get_mut(), + parts.get_mut(), + ); fmt.pad_formatted_parts(&formatted) } } @@ -85,31 +125,42 @@ fn float_to_exponential_common_exact(fmt: &mut Formatter<'_>, num: &T, // Don't inline this so callers that call both this and the above won't wind // up using the combined stack space of both functions in some cases. #[inline(never)] -fn float_to_exponential_common_shortest(fmt: &mut Formatter<'_>, - num: &T, sign: flt2dec::Sign, - upper: bool) -> Result - where T: flt2dec::DecodableFloat +fn float_to_exponential_common_shortest( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + upper: bool, +) -> Result +where + T: flt2dec::DecodableFloat, { unsafe { // enough for f32 and f64 let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit(); let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit(); // FIXME(#53491) - let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest, - *num, sign, (0, 0), upper, - buf.get_mut(), parts.get_mut()); + let formatted = flt2dec::to_shortest_exp_str( + flt2dec::strategy::grisu::format_shortest, + *num, + sign, + (0, 0), + upper, + buf.get_mut(), + parts.get_mut(), + ); fmt.pad_formatted_parts(&formatted) } } // Common code of floating point LowerExp and UpperExp. fn float_to_exponential_common(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result - where T: flt2dec::DecodableFloat +where + T: flt2dec::DecodableFloat, { let force_sign = fmt.sign_plus(); let sign = match force_sign { false => flt2dec::Sign::Minus, - true => flt2dec::Sign::MinusPlus, + true => flt2dec::Sign::MinusPlus, }; if let Some(precision) = fmt.precision { @@ -121,7 +172,7 @@ fn float_to_exponential_common(fmt: &mut Formatter<'_>, num: &T, upper: bool) } macro_rules! floating { - ($ty:ident) => ( + ($ty:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for $ty { fn fmt(&self, fmt: &mut Formatter<'_>) -> Result { @@ -149,7 +200,7 @@ macro_rules! floating { float_to_exponential_common(fmt, self, true) } } - ) + }; } floating! { f32 } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0e83a282b1..223f91d909 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1,8 +1,10 @@ //! Utilities for formatting and printing strings. +// ignore-tidy-undocumented-unsafe + #![stable(feature = "rust1", since = "1.0.0")] -use crate::cell::{UnsafeCell, Cell, RefCell, Ref, RefMut}; +use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; use crate::marker::PhantomData; use crate::mem; use crate::num::flt2dec; @@ -11,9 +13,9 @@ use crate::result; use crate::slice; use crate::str; +mod builders; mod float; mod num; -mod builders; #[stable(feature = "fmt_flags_align", since = "1.28.0")] /// Possible alignments returned by `Formatter::align` @@ -31,10 +33,9 @@ pub enum Alignment { } #[stable(feature = "debug_builders", since = "1.2.0")] -pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}; +pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; -#[unstable(feature = "fmt_internals", reason = "internal to format_args!", - issue = "0")] +#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] #[doc(hidden)] pub mod rt { pub mod v1; @@ -232,7 +233,7 @@ pub struct Formatter<'a> { width: Option, precision: Option, - buf: &'a mut (dyn Write+'a), + buf: &'a mut (dyn Write + 'a), curarg: slice::Iter<'a, ArgumentV1<'a>>, args: &'a [ArgumentV1<'a>], } @@ -258,8 +259,7 @@ struct Void { /// types, and then this struct is used to canonicalize arguments to one type. #[derive(Copy, Clone)] #[allow(missing_debug_implementations)] -#[unstable(feature = "fmt_internals", reason = "internal to format_args!", - issue = "0")] +#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] #[doc(hidden)] pub struct ArgumentV1<'a> { value: &'a Void, @@ -273,21 +273,13 @@ impl<'a> ArgumentV1<'a> { } #[doc(hidden)] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", - issue = "0")] - pub fn new<'b, T>(x: &'b T, - f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> { - unsafe { - ArgumentV1 { - formatter: mem::transmute(f), - value: mem::transmute(x) - } - } + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] + pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> { + unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } } } #[doc(hidden)] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", - issue = "0")] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] pub fn from_usize(x: &usize) -> ArgumentV1<'_> { ArgumentV1::new(x, ArgumentV1::show_usize) } @@ -303,21 +295,23 @@ impl<'a> ArgumentV1<'a> { // flags available in the v1 format of format_args #[derive(Copy, Clone)] -enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex } +enum FlagV1 { + SignPlus, + SignMinus, + Alternate, + SignAwareZeroPad, + DebugLowerHex, + DebugUpperHex, +} impl<'a> Arguments<'a> { /// When using the format_args!() macro, this function is used to generate the /// Arguments structure. - #[doc(hidden)] #[inline] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", - issue = "0")] - pub fn new_v1(pieces: &'a [&'a str], - args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { - Arguments { - pieces, - fmt: None, - args, - } + #[doc(hidden)] + #[inline] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] + pub fn new_v1(pieces: &'a [&'a str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { + Arguments { pieces, fmt: None, args } } /// This function is used to specify nonstandard formatting parameters. @@ -326,29 +320,26 @@ impl<'a> Arguments<'a> { /// `CountIsParam` or `CountIsNextParam` has to point to an argument /// created with `argumentusize`. However, failing to do so doesn't cause /// unsafety, but will ignore invalid . - #[doc(hidden)] #[inline] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", - issue = "0")] - pub fn new_v1_formatted(pieces: &'a [&'a str], - args: &'a [ArgumentV1<'a>], - fmt: &'a [rt::v1::Argument]) -> Arguments<'a> { - Arguments { - pieces, - fmt: Some(fmt), - args, - } + #[doc(hidden)] + #[inline] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] + pub fn new_v1_formatted( + pieces: &'a [&'a str], + args: &'a [ArgumentV1<'a>], + fmt: &'a [rt::v1::Argument], + ) -> Arguments<'a> { + Arguments { pieces, fmt: Some(fmt), args } } /// Estimates the length of the formatted text. /// /// This is intended to be used for setting initial `String` capacity /// when using `format!`. Note: this is neither the lower nor upper bound. - #[doc(hidden)] #[inline] - #[unstable(feature = "fmt_internals", reason = "internal to format_args!", - issue = "0")] + #[doc(hidden)] + #[inline] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")] pub fn estimated_capacity(&self) -> usize { - let pieces_length: usize = self.pieces.iter() - .map(|x| x.len()).sum(); + let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum(); if self.args.is_empty() { pieces_length @@ -512,10 +503,13 @@ impl Display for Arguments<'_> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented( - on(crate_local, label="`{Self}` cannot be formatted using `{{:?}}`", - note="add `#[derive(Debug)]` or manually implement `{Debug}`"), - message="`{Self}` doesn't implement `{Debug}`", - label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", + on( + crate_local, + label = "`{Self}` cannot be formatted using `{{:?}}`", + note = "add `#[derive(Debug)]` or manually implement `{Debug}`" + ), + message = "`{Self}` doesn't implement `{Debug}`", + label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`" )] #[doc(alias = "{:?}")] #[rustc_diagnostic_item = "debug_trait"] @@ -551,7 +545,9 @@ pub(crate) mod macros { #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] - pub macro Debug($item:item) { /* compiler built-in */ } + pub macro Debug($item:item) { + /* compiler built-in */ + } } #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] @@ -592,14 +588,14 @@ pub use macros::Debug; /// ``` #[rustc_on_unimplemented( on( - _Self="std::path::Path", - label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it", - note="call `.display()` or `.to_string_lossy()` to safely print paths, \ - as they may contain non-Unicode data" + _Self = "std::path::Path", + label = "`{Self}` cannot be formatted with the default formatter; call `.display()` on it", + note = "call `.display()` or `.to_string_lossy()` to safely print paths, \ + as they may contain non-Unicode data" ), - message="`{Self}` doesn't implement `{Display}`", - label="`{Self}` cannot be formatted with the default formatter", - note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead", + message = "`{Self}` doesn't implement `{Display}`", + label = "`{Self}` cannot be formatted with the default formatter", + note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead" )] #[doc(alias = "{}")] #[stable(feature = "rust1", since = "1.0.0")] @@ -666,7 +662,7 @@ pub trait Display { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// let val = self.0; /// -/// write!(f, "{:o}", val) // delegate to i32's implementation +/// fmt::Octal::fmt(&val, f) // delegate to i32's implementation /// } /// } /// @@ -716,7 +712,7 @@ pub trait Octal { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// let val = self.0; /// -/// write!(f, "{:b}", val) // delegate to i32's implementation +/// fmt::Binary::fmt(&val, f) // delegate to i32's implementation /// } /// } /// @@ -775,7 +771,7 @@ pub trait Binary { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// let val = self.0; /// -/// write!(f, "{:x}", val) // delegate to i32's implementation +/// fmt::LowerHex::fmt(&val, f) // delegate to i32's implementation /// } /// } /// @@ -828,7 +824,7 @@ pub trait LowerHex { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// let val = self.0; /// -/// write!(f, "{:X}", val) // delegate to i32's implementation +/// fmt::UpperHex::fmt(&val, f) // delegate to i32's implementation /// } /// } /// @@ -873,7 +869,8 @@ pub trait UpperHex { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// // use `as` to convert to a `*const T`, which implements Pointer, which we can use /// -/// write!(f, "{:p}", self as *const Length) +/// let ptr = self as *const Self; +/// fmt::Pointer::fmt(&ptr, f) /// } /// } /// @@ -1071,7 +1068,9 @@ impl PostPadding { impl<'a> Formatter<'a> { fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c> - where 'b: 'c, F: FnOnce(&'b mut (dyn Write+'b)) -> &'c mut (dyn Write+'c) + where + 'b: 'c, + F: FnOnce(&'b mut (dyn Write + 'b)) -> &'c mut (dyn Write + 'c), { Formatter { // We want to change this @@ -1104,7 +1103,7 @@ impl<'a> Formatter<'a> { // Extract the correct argument let value = match arg.position { - rt::v1::Position::Next => { *self.curarg.next().unwrap() } + rt::v1::Position::Next => *self.curarg.next().unwrap(), rt::v1::Position::At(i) => self.args[i], }; @@ -1116,12 +1115,8 @@ impl<'a> Formatter<'a> { match *cnt { rt::v1::Count::Is(n) => Some(n), rt::v1::Count::Implied => None, - rt::v1::Count::Param(i) => { - self.args[i].as_usize() - } - rt::v1::Count::NextParam => { - self.curarg.next()?.as_usize() - } + rt::v1::Count::Param(i) => self.args[i].as_usize(), + rt::v1::Count::NextParam => self.curarg.next()?.as_usize(), } } @@ -1172,18 +1167,16 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn pad_integral(&mut self, - is_nonnegative: bool, - prefix: &str, - buf: &str) - -> Result { + pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result { let mut width = buf.len(); let mut sign = None; if !is_nonnegative { - sign = Some('-'); width += 1; + sign = Some('-'); + width += 1; } else if self.sign_plus() { - sign = Some('+'); width += 1; + sign = Some('+'); + width += 1; } let prefix = if self.alternate() { @@ -1199,11 +1192,7 @@ impl<'a> Formatter<'a> { if let Some(c) = sign { f.buf.write_char(c)?; } - if let Some(prefix) = prefix { - f.buf.write_str(prefix) - } else { - Ok(()) - } + if let Some(prefix) = prefix { f.buf.write_str(prefix) } else { Ok(()) } } // The `width` field is more of a `min-width` parameter at this point. @@ -1299,9 +1288,7 @@ impl<'a> Formatter<'a> { None => self.buf.write_str(s), // If we're under the maximum width, check if we're over the minimum // width, if so it's as easy as just emitting the string. - Some(width) if s.chars().count() >= width => { - self.buf.write_str(s) - } + Some(width) if s.chars().count() >= width => self.buf.write_str(s), // If we're under both the maximum and the minimum width, then fill // up the minimum width with the specified string + some alignment. Some(width) => { @@ -1319,17 +1306,16 @@ impl<'a> Formatter<'a> { fn padding( &mut self, padding: usize, - default: rt::v1::Alignment + default: rt::v1::Alignment, ) -> result::Result { let align = match self.align { rt::v1::Alignment::Unknown => default, - _ => self.align + _ => self.align, }; let (pre_pad, post_pad) = match align { rt::v1::Alignment::Left => (0, padding), - rt::v1::Alignment::Right | - rt::v1::Alignment::Unknown => (padding, 0), + rt::v1::Alignment::Right | rt::v1::Alignment::Unknown => (padding, 0), rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2), }; @@ -1366,7 +1352,8 @@ impl<'a> Formatter<'a> { // remaining parts go through the ordinary padding process. let len = formatted.len(); - let ret = if width <= len { // no padding + let ret = if width <= len { + // no padding self.write_formatted_parts(&formatted) } else { let post_padding = self.padding(width - len, align)?; @@ -1471,10 +1458,14 @@ impl<'a> Formatter<'a> { /// Flags for formatting #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.24.0", - reason = "use the `sign_plus`, `sign_minus`, `alternate`, \ - or `sign_aware_zero_pad` methods instead")] - pub fn flags(&self) -> u32 { self.flags } + #[rustc_deprecated( + since = "1.24.0", + reason = "use the `sign_plus`, `sign_minus`, `alternate`, \ + or `sign_aware_zero_pad` methods instead" + )] + pub fn flags(&self) -> u32 { + self.flags + } /// Character used as 'fill' whenever there is alignment. /// @@ -1504,7 +1495,9 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{:t>6}", Foo), "tttttt"); /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] - pub fn fill(&self) -> char { self.fill } + pub fn fill(&self) -> char { + self.fill + } /// Flag indicating what form of alignment was requested. /// @@ -1572,7 +1565,9 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] - pub fn width(&self) -> Option { self.width } + pub fn width(&self) -> Option { + self.width + } /// Optionally specified precision for numeric types. /// @@ -1599,7 +1594,9 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)"); /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] - pub fn precision(&self) -> Option { self.precision } + pub fn precision(&self) -> Option { + self.precision + } /// Determines if the `+` flag was specified. /// @@ -1627,7 +1624,9 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] - pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 } + pub fn sign_plus(&self) -> bool { + self.flags & (1 << FlagV1::SignPlus as u32) != 0 + } /// Determines if the `-` flag was specified. /// @@ -1653,7 +1652,9 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] - pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 } + pub fn sign_minus(&self) -> bool { + self.flags & (1 << FlagV1::SignMinus as u32) != 0 + } /// Determines if the `#` flag was specified. /// @@ -1678,7 +1679,9 @@ impl<'a> Formatter<'a> { /// assert_eq!(&format!("{}", Foo(23)), "23"); /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] - pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 } + pub fn alternate(&self) -> bool { + self.flags & (1 << FlagV1::Alternate as u32) != 0 + } /// Determines if the `0` flag was specified. /// @@ -1707,9 +1710,13 @@ impl<'a> Formatter<'a> { // FIXME: Decide what public API we want for these two flags. // https://github.com/rust-lang/rust/issues/48584 - fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 } + fn debug_lower_hex(&self) -> bool { + self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 + } - fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 } + fn debug_upper_hex(&self) -> bool { + self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 + } /// Creates a [`DebugStruct`] builder designed to assist with creation of /// [`fmt::Debug`] implementations for structs. @@ -2065,11 +2072,15 @@ impl Pointer for &mut T { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for *const T { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(self, f) } + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Pointer::fmt(self, f) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Debug for *mut T { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(self, f) } + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Pointer::fmt(self, f) + } } macro_rules! peel { @@ -2127,9 +2138,7 @@ impl Debug for PhantomData { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for Cell { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - f.debug_struct("Cell") - .field("value", &self.get()) - .finish() + f.debug_struct("Cell").field("value", &self.get()).finish() } } @@ -2137,11 +2146,7 @@ impl Debug for Cell { impl Debug for RefCell { fn fmt(&self, f: &mut Formatter<'_>) -> Result { match self.try_borrow() { - Ok(borrow) => { - f.debug_struct("RefCell") - .field("value", &borrow) - .finish() - } + Ok(borrow) => f.debug_struct("RefCell").field("value", &borrow).finish(), Err(_) => { // The RefCell is mutably borrowed so we can't look at its value // here. Show a placeholder instead. @@ -2153,9 +2158,7 @@ impl Debug for RefCell { } } - f.debug_struct("RefCell") - .field("value", &BorrowedPlaceholder) - .finish() + f.debug_struct("RefCell").field("value", &BorrowedPlaceholder).finish() } } } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 3b5c9fbff2..3c7aefc090 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -1,5 +1,7 @@ //! Integer and floating-point number formatting +// ignore-tidy-undocumented-unsafe + use crate::fmt; use crate::ops::{Div, Rem, Sub}; diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 020e085abf..0db8d86ebb 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -79,6 +79,8 @@ //! } //! ``` +// ignore-tidy-undocumented-unsafe + #![stable(feature = "rust1", since = "1.0.0")] use crate::fmt; @@ -190,7 +192,8 @@ pub trait Hash { /// [`Hasher`]: trait.Hasher.html #[stable(feature = "hash_slice", since = "1.3.0")] fn hash_slice(data: &[Self], state: &mut H) - where Self: Sized + where + Self: Sized, { for piece in data { piece.hash(state); @@ -204,7 +207,9 @@ pub(crate) mod macros { #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] - pub macro Hash($item:item) { /* compiler built-in */ } + pub macro Hash($item:item) { + /* compiler built-in */ + } } #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] @@ -664,7 +669,6 @@ mod impls { } } - #[stable(feature = "rust1", since = "1.0.0")] impl Hash for &T { fn hash(&self, state: &mut H) { @@ -687,9 +691,7 @@ mod impls { state.write_usize(*self as *const () as usize); } else { // Fat pointer - let (a, b) = unsafe { - *(self as *const Self as *const (usize, usize)) - }; + let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; state.write_usize(a); state.write_usize(b); } @@ -704,9 +706,7 @@ mod impls { state.write_usize(*self as *const () as usize); } else { // Fat pointer - let (a, b) = unsafe { - *(self as *const Self as *const (usize, usize)) - }; + let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) }; state.write_usize(a); state.write_usize(b); } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 19aeafd882..0aa3b97ebc 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -1,11 +1,13 @@ //! An implementation of SipHash. +// ignore-tidy-undocumented-unsafe + #![allow(deprecated)] // the types in this module are deprecated -use crate::marker::PhantomData; -use crate::ptr; use crate::cmp; +use crate::marker::PhantomData; use crate::mem; +use crate::ptr; /// An implementation of SipHash 1-3. /// @@ -14,8 +16,10 @@ use crate::mem; /// /// See: #[unstable(feature = "hashmap_internals", issue = "0")] -#[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] +#[rustc_deprecated( + since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead" +)] #[derive(Debug, Clone, Default)] #[doc(hidden)] pub struct SipHasher13 { @@ -26,8 +30,10 @@ pub struct SipHasher13 { /// /// See: #[unstable(feature = "hashmap_internals", issue = "0")] -#[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] +#[rustc_deprecated( + since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead" +)] #[derive(Debug, Clone, Default)] struct SipHasher24 { hasher: Hasher, @@ -46,8 +52,10 @@ struct SipHasher24 { /// it is not intended for cryptographic purposes. As such, all /// cryptographic uses of this implementation are _strongly discouraged_. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] +#[rustc_deprecated( + since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead" +)] #[derive(Debug, Clone, Default)] pub struct SipHasher(SipHasher24); @@ -56,9 +64,9 @@ struct Hasher { k0: u64, k1: u64, length: usize, // how many bytes we've processed - state: State, // hash State - tail: u64, // unprocessed bytes le - ntail: usize, // how many bytes in tail are valid + state: State, // hash State + tail: u64, // unprocessed bytes le + ntail: usize, // how many bytes in tail are valid _marker: PhantomData, } @@ -76,18 +84,23 @@ struct State { } macro_rules! compress { - ($state:expr) => ({ - compress!($state.v0, $state.v1, $state.v2, $state.v3) - }); - ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => - ({ - $v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0; + ($state:expr) => {{ compress!($state.v0, $state.v1, $state.v2, $state.v3) }}; + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{ + $v0 = $v0.wrapping_add($v1); + $v1 = $v1.rotate_left(13); + $v1 ^= $v0; $v0 = $v0.rotate_left(32); - $v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2; - $v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0; - $v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2; + $v2 = $v2.wrapping_add($v3); + $v3 = $v3.rotate_left(16); + $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); + $v3 = $v3.rotate_left(21); + $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); + $v1 = $v1.rotate_left(17); + $v1 ^= $v2; $v2 = $v2.rotate_left(32); - }); + }}; } /// Loads an integer of the desired type from a byte stream, in LE order. Uses @@ -96,15 +109,16 @@ macro_rules! compress { /// /// Unsafe because: unchecked indexing at i..i+size_of(int_ty) macro_rules! load_int_le { - ($buf:expr, $i:expr, $int_ty:ident) => - ({ - debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); - let mut data = 0 as $int_ty; - ptr::copy_nonoverlapping($buf.get_unchecked($i), - &mut data as *mut _ as *mut u8, - mem::size_of::<$int_ty>()); - data.to_le() - }); + ($buf:expr, $i:expr, $int_ty:ident) => {{ + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping( + $buf.get_unchecked($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>(), + ); + data.to_le() + }}; } /// Loads an u64 using up to 7 bytes of a byte slice. @@ -135,8 +149,10 @@ impl SipHasher { /// Creates a new `SipHasher` with the two initial keys set to 0. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] + #[rustc_deprecated( + since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead" + )] pub fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -144,12 +160,12 @@ impl SipHasher { /// Creates a `SipHasher` that is keyed off the provided keys. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] + #[rustc_deprecated( + since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead" + )] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { - SipHasher(SipHasher24 { - hasher: Hasher::new_with_keys(key0, key1) - }) + SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) }) } } @@ -157,8 +173,10 @@ impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] #[unstable(feature = "hashmap_internals", issue = "0")] - #[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] + #[rustc_deprecated( + since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead" + )] pub fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -166,12 +184,12 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] #[unstable(feature = "hashmap_internals", issue = "0")] - #[rustc_deprecated(since = "1.13.0", - reason = "use `std::collections::hash_map::DefaultHasher` instead")] + #[rustc_deprecated( + since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead" + )] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { - SipHasher13 { - hasher: Hasher::new_with_keys(key0, key1) - } + SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } } } @@ -182,12 +200,7 @@ impl Hasher { k0: key0, k1: key1, length: 0, - state: State { - v0: 0, - v1: 0, - v2: 0, - v3: 0, - }, + state: State { v0: 0, v1: 0, v2: 0, v3: 0 }, tail: 0, ntail: 0, _marker: PhantomData, @@ -292,7 +305,7 @@ impl super::Hasher for Hasher { self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail; if length < needed { self.ntail += length; - return + return; } else { self.state.v3 ^= self.tail; S::c_rounds(&mut self.state); diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 368a2f16b2..f4fb9ab175 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -2,6 +2,8 @@ //! Hints to compiler that affects how code should be emitted or optimized. +// ignore-tidy-undocumented-unsafe + use crate::intrinsics; /// Informs the compiler that this point in the code is not reachable, enabling @@ -62,31 +64,27 @@ pub unsafe fn unreachable_unchecked() -> ! { #[inline] #[unstable(feature = "renamed_spin_loop", issue = "55002")] pub fn spin_loop() { - #[cfg( - all( - any(target_arch = "x86", target_arch = "x86_64"), - target_feature = "sse2" - ) - )] { - #[cfg(target_arch = "x86")] { + #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))] + { + #[cfg(target_arch = "x86")] + { unsafe { crate::arch::x86::_mm_pause() }; } - #[cfg(target_arch = "x86_64")] { + #[cfg(target_arch = "x86_64")] + { unsafe { crate::arch::x86_64::_mm_pause() }; } } - #[cfg( - any( - target_arch = "aarch64", - all(target_arch = "arm", target_feature = "v6") - ) - )] { - #[cfg(target_arch = "aarch64")] { + #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))] + { + #[cfg(target_arch = "aarch64")] + { unsafe { crate::arch::aarch64::__yield() }; } - #[cfg(target_arch = "arm")] { + #[cfg(target_arch = "arm")] + { unsafe { crate::arch::arm::__yield() }; } } @@ -111,7 +109,7 @@ pub fn spin_loop() { pub fn black_box(dummy: T) -> T { // We need to "use" the argument in some way LLVM can't introspect, and on // targets that support it we can typically leverage inline assembly to do - // this. LLVM's intepretation of inline assembly is that it's, well, a black + // this. LLVM's interpretation of inline assembly is that it's, well, a black // box. This isn't the greatest implementation since it probably deoptimizes // more than we want, but it's so far good enough. unsafe { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 3db85d05d7..1f72b7ab09 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -697,7 +697,6 @@ extern "rust-intrinsic" { pub fn panic_if_uninhabited(); /// Gets a reference to a static `Location` indicating where it was called. - #[cfg(not(bootstrap))] pub fn caller_location() -> &'static crate::panic::Location<'static>; /// Creates a value initialized to zero. @@ -940,6 +939,11 @@ extern "rust-intrinsic" { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_transmute"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_transmute", issue = "53605"), + )] pub fn transmute(e: T) -> U; /// Returns `true` if the actual type given as `T` requires drop @@ -1144,6 +1148,11 @@ extern "rust-intrinsic" { /// May assume inputs are finite. pub fn frem_fast(a: T, b: T) -> T; + /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range + /// https://github.com/rust-lang/rust/issues/10184 + #[cfg(not(bootstrap))] + pub fn float_to_int_approx_unchecked(value: Float) -> Int; + /// Returns the number of bits set in an integer type `T` pub fn ctpop(x: T) -> T; @@ -1280,7 +1289,7 @@ extern "rust-intrinsic" { /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`. pub fn unchecked_add(x: T, y: T) -> T; - /// Returns the result of an unchecked substraction, resulting in + /// Returns the result of an unchecked subtraction, resulting in /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`. pub fn unchecked_sub(x: T, y: T) -> T; @@ -1346,8 +1355,14 @@ extern "rust-intrinsic" { pub fn nontemporal_store(ptr: *mut T, val: T); /// See documentation of `<*const T>::offset_from` for details. - #[cfg(not(bootstrap))] pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; + + /// Internal hook used by Miri to implement unwinding. + /// Compiles to a NOP during non-Miri codegen. + /// + /// Perma-unstable: do not use + #[cfg(not(bootstrap))] + pub fn miri_start_panic(data: *mut (dyn crate::any::Any + crate::marker::Send)) -> (); } // Some functions are defined here because they accidentally got made diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs index c9612596b1..3b669cad1c 100644 --- a/src/libcore/iter/adapters/chain.rs +++ b/src/libcore/iter/adapters/chain.rs @@ -3,7 +3,7 @@ use crate::usize; use super::super::{Iterator, DoubleEndedIterator, FusedIterator, TrustedLen}; -/// An iterator that strings two iterators together. +/// An iterator that links two iterators together, in a chain. /// /// This `struct` is created by the [`chain`] method on [`Iterator`]. See its /// documentation for more. diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index a45173f614..0a7a9f26f8 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -1,7 +1,7 @@ use crate::fmt; use crate::ops::Try; -use super::super::{Iterator, DoubleEndedIterator, FusedIterator}; +use super::super::{DoubleEndedIterator, FusedIterator, Iterator}; use super::Map; /// An iterator that maps each element to an iterator, and yields the elements @@ -15,7 +15,7 @@ use super::Map; #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct FlatMap { - inner: FlattenCompat, ::IntoIter> + inner: FlattenCompat, ::IntoIter>, } impl U> FlatMap { pub(in super::super) fn new(iter: I, f: F) -> FlatMap { @@ -28,7 +28,9 @@ impl Clone for FlatMap where U: Clone + IntoIterator, { - fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } } + fn clone(&self) -> Self { + FlatMap { inner: self.inner.clone() } + } } #[stable(feature = "core_impl_debug", since = "1.9.0")] @@ -43,26 +45,35 @@ where #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for FlatMap - where F: FnMut(I::Item) -> U, +where + F: FnMut(I::Item) -> U, { type Item = U::Item; #[inline] - fn next(&mut self) -> Option { self.inner.next() } + fn next(&mut self) -> Option { + self.inner.next() + } #[inline] - fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, { self.inner.try_fold(init, fold) } #[inline] fn fold(self, init: Acc, fold: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.fold(init, fold) } @@ -75,18 +86,24 @@ where U: IntoIterator, { #[inline] - fn next_back(&mut self) -> Option { self.inner.next_back() } + fn next_back(&mut self) -> Option { + self.inner.next_back() + } #[inline] - fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, { self.inner.try_rfold(init, fold) } #[inline] fn rfold(self, init: Acc, fold: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.rfold(init, fold) } @@ -94,7 +111,12 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for FlatMap - where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {} +where + I: FusedIterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, +{ +} /// An iterator that flattens one level of nesting in an iterator of things /// that can be turned into iterators. @@ -133,7 +155,9 @@ where I: Clone + Iterator>, U: Clone + Iterator, { - fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } } + fn clone(&self) -> Self { + Flatten { inner: self.inner.clone() } + } } #[stable(feature = "iterator_flatten", since = "1.29.0")] @@ -145,21 +169,29 @@ where type Item = U::Item; #[inline] - fn next(&mut self) -> Option { self.inner.next() } + fn next(&mut self) -> Option { + self.inner.next() + } #[inline] - fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + fn try_fold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, { self.inner.try_fold(init, fold) } #[inline] fn fold(self, init: Acc, fold: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.fold(init, fold) } @@ -172,18 +204,24 @@ where U: DoubleEndedIterator, { #[inline] - fn next_back(&mut self) -> Option { self.inner.next_back() } + fn next_back(&mut self) -> Option { + self.inner.next_back() + } #[inline] - fn try_rfold(&mut self, init: Acc, fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + fn try_rfold(&mut self, init: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, { self.inner.try_rfold(init, fold) } #[inline] fn rfold(self, init: Acc, fold: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { self.inner.rfold(init, fold) } @@ -194,7 +232,8 @@ impl FusedIterator for Flatten where I: FusedIterator>, U: Iterator, -{} +{ +} /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. @@ -222,7 +261,9 @@ where fn next(&mut self) -> Option { loop { if let Some(ref mut inner) = self.frontiter { - if let elt@Some(_) = inner.next() { return elt } + if let elt @ Some(_) = inner.next() { + return elt; + } } match self.iter.next() { None => return self.backiter.as_mut()?.next(), @@ -238,13 +279,16 @@ where let lo = flo.saturating_add(blo); match (self.iter.size_hint(), fhi, bhi) { ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), - _ => (lo, None) + _ => (lo, None), } } #[inline] - fn try_fold(&mut self, mut init: Acc, mut fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + fn try_fold(&mut self, mut init: Acc, mut fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, { #[inline] fn flatten<'a, T: IntoIterator, Acc, R: Try>( @@ -277,7 +321,8 @@ where #[inline] fn fold(self, init: Acc, ref mut fold: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { #[inline] fn flatten( @@ -286,7 +331,8 @@ where move |acc, iter| iter.fold(acc, &mut *fold) } - self.frontiter.into_iter() + self.frontiter + .into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) .fold(init, flatten(fold)) @@ -302,7 +348,9 @@ where fn next_back(&mut self) -> Option { loop { if let Some(ref mut inner) = self.backiter { - if let elt@Some(_) = inner.next_back() { return elt } + if let elt @ Some(_) = inner.next_back() { + return elt; + } } match self.iter.next_back() { None => return self.frontiter.as_mut()?.next_back(), @@ -312,14 +360,18 @@ where } #[inline] - fn try_rfold(&mut self, mut init: Acc, mut fold: Fold) -> R where - Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try + fn try_rfold(&mut self, mut init: Acc, mut fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, { #[inline] fn flatten<'a, T: IntoIterator, Acc, R: Try>( backiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, T::Item) -> R, - ) -> impl FnMut(Acc, T) -> R + 'a where + ) -> impl FnMut(Acc, T) -> R + 'a + where T::IntoIter: DoubleEndedIterator, { move |acc, x| { @@ -348,7 +400,8 @@ where #[inline] fn rfold(self, init: Acc, ref mut fold: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, + where + Fold: FnMut(Acc, Self::Item) -> Acc, { #[inline] fn flatten( @@ -357,7 +410,8 @@ where move |acc, iter| iter.rfold(acc, &mut *fold) } - self.frontiter.into_iter() + self.frontiter + .into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) .rfold(init, flatten(fold)) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 3b8edc2ad6..39d571006e 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -517,8 +517,18 @@ impl Iterator for StepBy where I: Iterator { // overflow handling loop { let mul = n.checked_mul(step); - if unsafe { intrinsics::likely(mul.is_some()) } { - return self.iter.nth(mul.unwrap() - 1); + #[cfg(bootstrap)] + { + // SAFETY: going away soon + if unsafe { intrinsics::likely(mul.is_some()) } { + return self.iter.nth(mul.unwrap() - 1); + } + } + #[cfg(not(bootstrap))] + { + if intrinsics::likely(mul.is_some()) { + return self.iter.nth(mul.unwrap() - 1); + } } let div_n = usize::MAX / n; let div_step = usize::MAX / step; diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs index 430ceacdd9..14d9d5499b 100644 --- a/src/libcore/iter/adapters/zip.rs +++ b/src/libcore/iter/adapters/zip.rs @@ -1,3 +1,5 @@ +// ignore-tidy-undocumented-unsafe + use crate::cmp; use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen}; diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index efda3b263c..63036f516a 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -20,10 +20,14 @@ pub trait Step: Clone + PartialOrd + Sized { /// without overflow. fn steps_between(start: &Self, end: &Self) -> Option; - /// Replaces this step with `1`, returning itself. + /// Replaces this step with `1`, returning a clone of itself. + /// + /// The output of this method should always be greater than the output of replace_zero. fn replace_one(&mut self) -> Self; - /// Replaces this step with `0`, returning itself. + /// Replaces this step with `0`, returning a clone of itself. + /// + /// The output of this method should always be less than the output of replace_one. fn replace_zero(&mut self) -> Self; /// Adds one to this step, returning the result. diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 183176005e..127b778e62 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -12,7 +12,7 @@ use super::{FusedIterator, TrustedLen}; #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Repeat { - element: A + element: A, } #[stable(feature = "rust1", since = "1.0.0")] @@ -20,15 +20,21 @@ impl Iterator for Repeat { type Item = A; #[inline] - fn next(&mut self) -> Option { Some(self.element.clone()) } + fn next(&mut self) -> Option { + Some(self.element.clone()) + } #[inline] - fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for Repeat { #[inline] - fn next_back(&mut self) -> Option { Some(self.element.clone()) } + fn next_back(&mut self) -> Option { + Some(self.element.clone()) + } } #[stable(feature = "fused", since = "1.26.0")] @@ -91,7 +97,7 @@ unsafe impl TrustedLen for Repeat {} #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn repeat(elt: T) -> Repeat { - Repeat{element: elt} + Repeat { element: elt } } /// An iterator that repeats elements of type `A` endlessly by @@ -104,7 +110,7 @@ pub fn repeat(elt: T) -> Repeat { #[derive(Copy, Clone, Debug)] #[stable(feature = "iterator_repeat_with", since = "1.28.0")] pub struct RepeatWith { - repeater: F + repeater: F, } #[stable(feature = "iterator_repeat_with", since = "1.28.0")] @@ -112,10 +118,14 @@ impl A> Iterator for RepeatWith { type Item = A; #[inline] - fn next(&mut self) -> Option { Some((self.repeater)()) } + fn next(&mut self) -> Option { + Some((self.repeater)()) + } #[inline] - fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } } #[stable(feature = "iterator_repeat_with", since = "1.28.0")] @@ -213,7 +223,7 @@ impl Iterator for Empty { None } - fn size_hint(&self) -> (usize, Option){ + fn size_hint(&self) -> (usize, Option) { (0, Some(0)) } } @@ -271,6 +281,7 @@ impl Default for Empty { /// assert_eq!(None, nope.next()); /// ``` #[stable(feature = "iter_empty", since = "1.2.0")] +#[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_iter_empty", since = "1.32.0"))] pub const fn empty() -> Empty { Empty(marker::PhantomData) } @@ -283,7 +294,7 @@ pub const fn empty() -> Empty { #[derive(Clone, Debug)] #[stable(feature = "iter_once", since = "1.2.0")] pub struct Once { - inner: crate::option::IntoIter + inner: crate::option::IntoIter, } #[stable(feature = "iter_once", since = "1.2.0")] @@ -530,7 +541,8 @@ pub fn once_with A>(gen: F) -> OnceWith { #[inline] #[stable(feature = "iter_from_fn", since = "1.34.0")] pub fn from_fn(f: F) -> FromFn - where F: FnMut() -> Option +where + F: FnMut() -> Option, { FromFn(f) } @@ -547,7 +559,8 @@ pub struct FromFn(F); #[stable(feature = "iter_from_fn", since = "1.34.0")] impl Iterator for FromFn - where F: FnMut() -> Option +where + F: FnMut() -> Option, { type Item = T; @@ -577,15 +590,13 @@ impl fmt::Debug for FromFn { /// ``` #[stable(feature = "iter_successors", since = "1.34.0")] pub fn successors(first: Option, succ: F) -> Successors - where F: FnMut(&T) -> Option +where + F: FnMut(&T) -> Option, { // If this function returned `impl Iterator` // it could be based on `unfold` and not need a dedicated type. // However having a named `Successors` type allows it to be `Clone` when `T` and `F` are. - Successors { - next: first, - succ, - } + Successors { next: first, succ } } /// An new iterator where each successive item is computed based on the preceding one. @@ -603,7 +614,8 @@ pub struct Successors { #[stable(feature = "iter_successors", since = "1.34.0")] impl Iterator for Successors - where F: FnMut(&T) -> Option +where + F: FnMut(&T) -> Option, { type Item = T; @@ -616,24 +628,16 @@ impl Iterator for Successors #[inline] fn size_hint(&self) -> (usize, Option) { - if self.next.is_some() { - (1, None) - } else { - (0, Some(0)) - } + if self.next.is_some() { (1, None) } else { (0, Some(0)) } } } #[stable(feature = "iter_successors", since = "1.34.0")] -impl FusedIterator for Successors - where F: FnMut(&T) -> Option -{} +impl FusedIterator for Successors where F: FnMut(&T) -> Option {} #[stable(feature = "iter_successors", since = "1.34.0")] impl fmt::Debug for Successors { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Successors") - .field("next", &self.next) - .finish() + f.debug_struct("Successors").field("next", &self.next).finish() } } diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index 818f033032..65af671ddf 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -1,6 +1,6 @@ -use crate::ops::{Mul, Add}; -use crate::num::Wrapping; use crate::iter; +use crate::num::Wrapping; +use crate::ops::{Add, Mul}; /// Trait to represent types that can be created by summing up an iterator. /// @@ -17,7 +17,7 @@ pub trait Sum: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// "summing up" the items. #[stable(feature = "iter_arith_traits", since = "1.12.0")] - fn sum>(iter: I) -> Self; + fn sum>(iter: I) -> Self; } /// Trait to represent types that can be created by multiplying elements of an @@ -36,7 +36,7 @@ pub trait Product: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// multiplying the items. #[stable(feature = "iter_arith_traits", since = "1.12.0")] - fn product>(iter: I) -> Self; + fn product>(iter: I) -> Self; } // N.B., explicitly use Add and Mul here to inherit overflow checks @@ -115,9 +115,10 @@ macro_rules! float_sum_product { integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_sum_product! { f32 f64 } -#[stable(feature = "iter_arith_traits_result", since="1.16.0")] +#[stable(feature = "iter_arith_traits_result", since = "1.16.0")] impl Sum> for Result - where T: Sum, +where + T: Sum, { /// Takes each element in the `Iterator`: if it is an `Err`, no further /// elements are taken, and the `Err` is returned. Should no `Err` occur, @@ -137,21 +138,24 @@ impl Sum> for Result /// assert_eq!(res, Ok(3)); /// ``` fn sum(iter: I) -> Result - where I: Iterator>, + where + I: Iterator>, { iter::process_results(iter, |i| i.sum()) } } -#[stable(feature = "iter_arith_traits_result", since="1.16.0")] +#[stable(feature = "iter_arith_traits_result", since = "1.16.0")] impl Product> for Result - where T: Product, +where + T: Product, { /// Takes each element in the `Iterator`: if it is an `Err`, no further /// elements are taken, and the `Err` is returned. Should no `Err` occur, /// the product of all elements is returned. fn product(iter: I) -> Result - where I: Iterator>, + where + I: Iterator>, { iter::process_results(iter, |i| i.product()) } diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 00a8641705..f21ab8dbc3 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -91,9 +91,9 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented( - message="a collection of type `{Self}` cannot be built from an iterator \ - over elements of type `{A}`", - label="a collection of type `{Self}` cannot be built from `std::iter::Iterator`", + message = "a value of type `{Self}` cannot be built from an iterator \ + over elements of type `{A}`", + label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" )] pub trait FromIterator: Sized { /// Creates a value from an iterator. @@ -116,7 +116,7 @@ pub trait FromIterator: Sized { /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn from_iter>(iter: T) -> Self; + fn from_iter>(iter: T) -> Self; } /// Conversion into an `Iterator`. @@ -205,6 +205,7 @@ pub trait FromIterator: Sized { /// .collect() /// } /// ``` +#[rustc_diagnostic_item = "IntoIterator"] #[stable(feature = "rust1", since = "1.0.0")] pub trait IntoIterator { /// The type of the elements being iterated over. @@ -213,7 +214,7 @@ pub trait IntoIterator { /// Which kind of iterator are we turning this into? #[stable(feature = "rust1", since = "1.0.0")] - type IntoIter: Iterator; + type IntoIter: Iterator; /// Creates an iterator from a value. /// @@ -339,7 +340,7 @@ pub trait Extend { /// assert_eq!("abcdef", &message); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn extend>(&mut self, iter: T); + fn extend>(&mut self, iter: T); } #[stable(feature = "extend_for_unit", since = "1.28.0")] diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs index 006b243ca4..104724d9fb 100644 --- a/src/libcore/iter/traits/double_ended.rs +++ b/src/libcore/iter/traits/double_ended.rs @@ -1,5 +1,5 @@ -use crate::ops::Try; use crate::iter::LoopState; +use crate::ops::Try; /// An iterator able to yield elements from both ends. /// @@ -113,7 +113,9 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "iter_nth_back", since = "1.37.0")] fn nth_back(&mut self, mut n: usize) -> Option { for x in self.rev() { - if n == 0 { return Some(x) } + if n == 0 { + return Some(x); + } n -= 1; } None @@ -157,7 +159,7 @@ pub trait DoubleEndedIterator: Iterator { where Self: Sized, F: FnMut(B, Self::Item) -> R, - R: Try + R: Try, { let mut accum = init; while let Some(x) = self.next_back() { @@ -279,7 +281,7 @@ pub trait DoubleEndedIterator: Iterator { fn rfind

(&mut self, predicate: P) -> Option where Self: Sized, - P: FnMut(&Self::Item) -> bool + P: FnMut(&Self::Item) -> bool, { #[inline] fn check( diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 7ffc8b3729..61e8b07511 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -201,12 +201,13 @@ pub trait Iterator { /// Consumes the iterator, counting the number of iterations and returning it. /// - /// This method will evaluate the iterator until its [`next`] returns - /// [`None`]. Once [`None`] is encountered, `count()` returns the number of - /// times it called [`next`]. + /// This method will call [`next`] repeatedly until [`None`] is encountered, + /// returning the number of times it saw [`Some`]. Note that [`next`] has to be + /// called at least once even if the iterator does not have any elements. /// /// [`next`]: #tymethod.next /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`Some`]: ../../std/option/enum.Option.html#variant.Some /// /// # Overflow Behavior /// @@ -1254,7 +1255,7 @@ pub trait Iterator { Fuse::new(self) } - /// Do something with each element of an iterator, passing the value on. + /// Does something with each element of an iterator, passing the value on. /// /// When using iterators, you'll often chain several of them together. /// While working on such code, you might want to check out what's @@ -1547,7 +1548,7 @@ pub trait Iterator { (left, right) } - /// Reorder the elements of this iterator *in-place* according to the given predicate, + /// Reorders the elements of this iterator *in-place* according to the given predicate, /// such that all those that return `true` precede all those that return `false`. /// Returns the number of `true` elements found. /// diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1b67b05c73..7fe4f7e41a 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -74,6 +74,8 @@ #![feature(const_fn)] #![feature(const_fn_union)] #![feature(const_generics)] +#![cfg_attr(not(bootstrap), feature(const_ptr_offset_from))] +#![cfg_attr(not(bootstrap), feature(const_type_name))] #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] @@ -89,17 +91,18 @@ #![feature(nll)] #![feature(exhaustive_patterns)] #![feature(no_core)] -#![feature(on_unimplemented)] +#![cfg_attr(bootstrap, feature(on_unimplemented))] #![feature(optin_builtin_traits)] #![feature(prelude_import)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] -#![feature(rustc_const_unstable)] +#![cfg_attr(bootstrap, feature(rustc_const_unstable))] #![feature(simd_ffi)] #![feature(specialization)] #![feature(staged_api)] #![feature(std_internals)] #![feature(stmt_expr_attributes)] +#![cfg_attr(not(bootstrap), feature(track_caller))] #![feature(transparent_unions)] #![feature(unboxed_closures)] #![feature(unsized_locals)] @@ -121,7 +124,6 @@ #![feature(hexagon_target_feature)] #![feature(const_int_conversion)] #![feature(const_transmute)] -#![cfg_attr(bootstrap, feature(non_exhaustive))] #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] diff --git a/src/libcore/macros.rs b/src/libcore/macros/mod.rs similarity index 88% rename from src/libcore/macros.rs rename to src/libcore/macros/mod.rs index 8ccd31c95d..cf460745ff 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros/mod.rs @@ -1,56 +1,28 @@ -/// Panics the current thread. -/// -/// For details, see `std::macros`. -#[cfg(bootstrap)] +#[doc(include = "panic.md")] #[macro_export] -#[allow_internal_unstable(core_panic, panic_internals)] +#[allow_internal_unstable(core_panic, + // FIXME(anp, eddyb) `core_intrinsics` is used here to allow calling + // the `caller_location` intrinsic, but once `#[track_caller]` is implemented, + // `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument. + core_intrinsics, +)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( $crate::panic!("explicit panic") ); - ($msg:expr) => ({ - $crate::panicking::panic(&($msg, $crate::file!(), $crate::line!(), $crate::column!())) - }); - ($msg:expr,) => ( - $crate::panic!($msg) - ); - ($fmt:expr, $($arg:tt)+) => ({ - $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), - &($crate::file!(), $crate::line!(), $crate::column!())) - }); -} - -/// Panics the current thread. -/// -/// For details, see `std::macros`. -#[cfg(not(bootstrap))] -#[macro_export] -#[allow_internal_unstable(core_panic, panic_internals)] -#[stable(feature = "core", since = "1.6.0")] -macro_rules! panic { - () => ( - $crate::panic!("explicit panic") + ($msg:expr) => ( + $crate::panicking::panic($msg, $crate::intrinsics::caller_location()) ); - ($msg:expr) => ({ - const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor( - $crate::file!(), - $crate::line!(), - $crate::column!(), - ); - $crate::panicking::panic($msg, LOC) - }); ($msg:expr,) => ( $crate::panic!($msg) ); - ($fmt:expr, $($arg:tt)+) => ({ - const LOC: &$crate::panic::Location<'_> = &$crate::panic::Location::internal_constructor( - $crate::file!(), - $crate::line!(), - $crate::column!(), - ); - $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), LOC) - }); + ($fmt:expr, $($arg:tt)+) => ( + $crate::panicking::panic_fmt( + $crate::format_args!($fmt, $($arg)+), + $crate::intrinsics::caller_location(), + ) + ); } /// Asserts that two expressions are equal to each other (using [`PartialEq`]). @@ -365,13 +337,17 @@ macro_rules! matches { #[rustc_deprecated(since = "1.39.0", reason = "use the `?` operator instead")] #[doc(alias = "?")] macro_rules! r#try { - ($expr:expr) => (match $expr { - $crate::result::Result::Ok(val) => val, - $crate::result::Result::Err(err) => { - return $crate::result::Result::Err($crate::convert::From::from(err)) + ($expr:expr) => { + match $expr { + $crate::result::Result::Ok(val) => val, + $crate::result::Result::Err(err) => { + return $crate::result::Result::Err($crate::convert::From::from(err)); + } } - }); - ($expr:expr,) => ($crate::r#try!($expr)); + }; + ($expr:expr,) => { + $crate::r#try!($expr) + }; } /// Writes formatted data into a buffer. @@ -762,8 +738,8 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! compile_error { - ($msg:expr) => ({ /* compiler built-in */ }); - ($msg:expr,) => ({ /* compiler built-in */ }) + ($msg:expr) => {{ /* compiler built-in */ }}; + ($msg:expr,) => {{ /* compiler built-in */ }}; } /// Constructs parameters for the other string-formatting macros. @@ -816,20 +792,23 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! format_args { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) + ($fmt:expr) => {{ /* compiler built-in */ }}; + ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; } /// Same as `format_args`, but adds a newline in the end. - #[unstable(feature = "format_args_nl", issue = "0", - reason = "`format_args_nl` is only for internal \ - language use and is subject to change")] + #[unstable( + feature = "format_args_nl", + issue = "0", + reason = "`format_args_nl` is only for internal \ + language use and is subject to change" + )] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] #[macro_export] macro_rules! format_args_nl { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) + ($fmt:expr) => {{ /* compiler built-in */ }}; + ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; } /// Inspects an environment variable at compile time. @@ -867,8 +846,8 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! env { - ($name:expr) => ({ /* compiler built-in */ }); - ($name:expr,) => ({ /* compiler built-in */ }) + ($name:expr) => {{ /* compiler built-in */ }}; + ($name:expr,) => {{ /* compiler built-in */ }}; } /// Optionally inspects an environment variable at compile time. @@ -894,8 +873,8 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! option_env { - ($name:expr) => ({ /* compiler built-in */ }); - ($name:expr,) => ({ /* compiler built-in */ }) + ($name:expr) => {{ /* compiler built-in */ }}; + ($name:expr,) => {{ /* compiler built-in */ }}; } /// Concatenates identifiers into one identifier. @@ -922,13 +901,16 @@ pub(crate) mod builtin { /// // fn concat_idents!(new, fun, name) { } // not usable in this way! /// # } /// ``` - #[unstable(feature = "concat_idents", issue = "29599", - reason = "`concat_idents` is not stable enough for use and is subject to change")] + #[unstable( + feature = "concat_idents", + issue = "29599", + reason = "`concat_idents` is not stable enough for use and is subject to change" + )] #[rustc_builtin_macro] #[macro_export] macro_rules! concat_idents { - ($($e:ident),+) => ({ /* compiler built-in */ }); - ($($e:ident,)+) => ({ /* compiler built-in */ }) + ($($e:ident),+) => {{ /* compiler built-in */ }}; + ($($e:ident,)+) => {{ /* compiler built-in */ }}; } /// Concatenates literals into a static string slice. @@ -950,8 +932,8 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! concat { - ($($e:expr),*) => ({ /* compiler built-in */ }); - ($($e:expr,)*) => ({ /* compiler built-in */ }) + ($($e:expr),*) => {{ /* compiler built-in */ }}; + ($($e:expr,)*) => {{ /* compiler built-in */ }}; } /// Expands to the line number on which it was invoked. @@ -978,7 +960,11 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - macro_rules! line { () => { /* compiler built-in */ } } + macro_rules! line { + () => { + /* compiler built-in */ + }; + } /// Expands to the column number at which it was invoked. /// @@ -1004,7 +990,11 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - macro_rules! column { () => { /* compiler built-in */ } } + macro_rules! column { + () => { + /* compiler built-in */ + }; + } /// Expands to the file name in which it was invoked. /// @@ -1029,7 +1019,11 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - macro_rules! file { () => { /* compiler built-in */ } } + macro_rules! file { + () => { + /* compiler built-in */ + }; + } /// Stringifies its arguments. /// @@ -1049,7 +1043,11 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - macro_rules! stringify { ($($t:tt)*) => { /* compiler built-in */ } } + macro_rules! stringify { + ($($t:tt)*) => { + /* compiler built-in */ + }; + } /// Includes a utf8-encoded file as a string. /// @@ -1085,8 +1083,8 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! include_str { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }) + ($file:expr) => {{ /* compiler built-in */ }}; + ($file:expr,) => {{ /* compiler built-in */ }}; } /// Includes a file as a reference to a byte array. @@ -1123,8 +1121,8 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! include_bytes { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }) + ($file:expr) => {{ /* compiler built-in */ }}; + ($file:expr,) => {{ /* compiler built-in */ }}; } /// Expands to a string that represents the current module path. @@ -1147,7 +1145,11 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - macro_rules! module_path { () => { /* compiler built-in */ } } + macro_rules! module_path { + () => { + /* compiler built-in */ + }; + } /// Evaluates boolean combinations of configuration flags at compile-time. /// @@ -1172,7 +1174,11 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - macro_rules! cfg { ($($cfg:tt)*) => { /* compiler built-in */ } } + macro_rules! cfg { + ($($cfg:tt)*) => { + /* compiler built-in */ + }; + } /// Parses a file as an expression or an item according to the context. /// @@ -1217,8 +1223,8 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! include { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }) + ($file:expr) => {{ /* compiler built-in */ }}; + ($file:expr,) => {{ /* compiler built-in */ }}; } /// Asserts that a boolean expression is `true` at runtime. @@ -1270,81 +1276,128 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] macro_rules! assert { - ($cond:expr) => ({ /* compiler built-in */ }); - ($cond:expr,) => ({ /* compiler built-in */ }); - ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }) + ($cond:expr) => {{ /* compiler built-in */ }}; + ($cond:expr,) => {{ /* compiler built-in */ }}; + ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }}; } /// Inline assembly. - #[unstable(feature = "asm", issue = "29722", - reason = "inline assembly is not stable enough for use and is subject to change")] + /// + /// Read the [unstable book] for the usage. + /// + /// [unstable book]: ../unstable-book/library-features/asm.html + #[unstable( + feature = "asm", + issue = "29722", + reason = "inline assembly is not stable enough for use and is subject to change" + )] #[rustc_builtin_macro] #[macro_export] - macro_rules! asm { ("assembly template" + macro_rules! asm { + ("assembly template" : $("output"(operand),)* : $("input"(operand),)* : $("clobbers",)* - : $("options",)*) => { /* compiler built-in */ } } + : $("options",)*) => { + /* compiler built-in */ + }; + } /// Module-level inline assembly. - #[unstable(feature = "global_asm", issue = "35119", - reason = "`global_asm!` is not stable enough for use and is subject to change")] + #[unstable( + feature = "global_asm", + issue = "35119", + reason = "`global_asm!` is not stable enough for use and is subject to change" + )] #[rustc_builtin_macro] #[macro_export] - macro_rules! global_asm { ("assembly") => { /* compiler built-in */ } } + macro_rules! global_asm { + ("assembly") => { + /* compiler built-in */ + }; + } /// Prints passed tokens into the standard output. - #[unstable(feature = "log_syntax", issue = "29598", - reason = "`log_syntax!` is not stable enough for use and is subject to change")] + #[unstable( + feature = "log_syntax", + issue = "29598", + reason = "`log_syntax!` is not stable enough for use and is subject to change" + )] #[rustc_builtin_macro] #[macro_export] - macro_rules! log_syntax { ($($arg:tt)*) => { /* compiler built-in */ } } + macro_rules! log_syntax { + ($($arg:tt)*) => { + /* compiler built-in */ + }; + } /// Enables or disables tracing functionality used for debugging other macros. - #[unstable(feature = "trace_macros", issue = "29598", - reason = "`trace_macros` is not stable enough for use and is subject to change")] + #[unstable( + feature = "trace_macros", + issue = "29598", + reason = "`trace_macros` is not stable enough for use and is subject to change" + )] #[rustc_builtin_macro] #[macro_export] macro_rules! trace_macros { - (true) => ({ /* compiler built-in */ }); - (false) => ({ /* compiler built-in */ }) + (true) => {{ /* compiler built-in */ }}; + (false) => {{ /* compiler built-in */ }}; } /// Attribute macro applied to a function to turn it into a unit test. #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - pub macro test($item:item) { /* compiler built-in */ } + pub macro test($item:item) { + /* compiler built-in */ + } /// Attribute macro applied to a function to turn it into a benchmark test. - #[unstable(soft, feature = "test", issue = "50297", - reason = "`bench` is a part of custom test frameworks which are unstable")] + #[unstable( + feature = "test", + issue = "50297", + soft, + reason = "`bench` is a part of custom test frameworks which are unstable" + )] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - pub macro bench($item:item) { /* compiler built-in */ } + pub macro bench($item:item) { + /* compiler built-in */ + } /// An implementation detail of the `#[test]` and `#[bench]` macros. - #[unstable(feature = "custom_test_frameworks", issue = "50297", - reason = "custom test frameworks are an unstable feature")] + #[unstable( + feature = "custom_test_frameworks", + issue = "50297", + reason = "custom test frameworks are an unstable feature" + )] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] - pub macro test_case($item:item) { /* compiler built-in */ } + pub macro test_case($item:item) { + /* compiler built-in */ + } /// Attribute macro applied to a static to register it as a global allocator. #[stable(feature = "global_allocator", since = "1.28.0")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] - pub macro global_allocator($item:item) { /* compiler built-in */ } + pub macro global_allocator($item:item) { + /* compiler built-in */ + } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)] - pub macro RustcDecodable($item:item) { /* compiler built-in */ } + pub macro RustcDecodable($item:item) { + /* compiler built-in */ + } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics)] - pub macro RustcEncodable($item:item) { /* compiler built-in */ } + pub macro RustcEncodable($item:item) { + /* compiler built-in */ + } } diff --git a/src/libcore/macros/panic.md b/src/libcore/macros/panic.md new file mode 100644 index 0000000000..3ecfc43be0 --- /dev/null +++ b/src/libcore/macros/panic.md @@ -0,0 +1,47 @@ +Panics the current thread. + +This allows a program to terminate immediately and provide feedback +to the caller of the program. `panic!` should be used when a program reaches +an unrecoverable state. + +This macro is the perfect way to assert conditions in example code and in +tests. `panic!` is closely tied with the `unwrap` method of both [`Option`] +and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set +to None or Err variants. + +This macro is used to inject panic into a Rust thread, causing the thread to +panic entirely. Each thread's panic can be reaped as the `Box` type, +and the single-argument form of the `panic!` macro will be the value which +is transmitted. + +[`Result`] enum is often a better solution for recovering from errors than +using the `panic!` macro. This macro should be used to avoid proceeding using +incorrect values, such as from external sources. Detailed information about +error handling is found in the [book]. + +The multi-argument form of this macro panics with a string and has the +[`format!`] syntax for building a string. + +See also the macro [`compile_error!`], for raising errors during compilation. + +[runwrap]: ../std/result/enum.Result.html#method.unwrap +[`Option`]: ../std/option/enum.Option.html#method.unwrap +[`Result`]: ../std/result/enum.Result.html +[`format!`]: ../std/macro.format.html +[`compile_error!`]: ../std/macro.compile_error.html +[book]: ../book/ch09-00-error-handling.html + +# Current implementation + +If the main thread panics it will terminate all your threads and end your +program with code `101`. + +# Examples + +```should_panic +# #![allow(unreachable_code)] +panic!(); +panic!("this is a terrible mistake!"); +panic!(4); // panic with the value of 4 to be collected elsewhere +panic!("this is a {} {message}", "fancy", message = "message"); +``` diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index a25573feab..1b586c3e5f 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -29,6 +29,7 @@ use crate::hash::Hasher; /// [arc]: ../../std/sync/struct.Arc.html /// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")] #[rustc_on_unimplemented( message="`{Self}` cannot be sent between threads safely", label="`{Self}` cannot be sent between threads safely" @@ -96,7 +97,7 @@ pub trait Sized { /// Types that can be "unsized" to a dynamically-sized type. /// /// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and -/// `Unsize`. +/// `Unsize`. /// /// All implementations of `Unsize` are provided automatically by the compiler. /// @@ -146,7 +147,6 @@ pub trait Unsize { /// /// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md /// [issue 63438]: https://github.com/rust-lang/rust/issues/63438 -#[cfg(not(bootstrap))] #[unstable(feature = "structural_match", issue = "31434")] #[rustc_on_unimplemented(message="the type `{Self}` does not `#[derive(PartialEq)]`")] #[lang = "structural_peq"] @@ -197,7 +197,6 @@ pub trait StructuralPartialEq { /// As a hack to work around this, we use two separate traits injected by each /// of the two derives (`#[derive(PartialEq)]` and `#[derive(Eq)]`) and check /// that both of them are present as part of structural-match checking. -#[cfg(not(bootstrap))] #[unstable(feature = "structural_match", issue = "31434")] #[rustc_on_unimplemented(message="the type `{Self}` does not `#[derive(Eq)]`")] #[lang = "structural_teq"] @@ -442,6 +441,7 @@ pub macro Copy($item:item) { /* compiler built-in */ } /// [ub]: ../../reference/behavior-considered-undefined.html /// [transmute]: ../../std/mem/fn.transmute.html #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "sync_trait")] #[lang = "sync"] #[rustc_on_unimplemented( message="`{Self}` cannot be shared between threads safely", @@ -517,11 +517,9 @@ macro_rules! impls{ } } - #[cfg(not(bootstrap))] #[unstable(feature = "structural_match", issue = "31434")] impl StructuralPartialEq for $t { } - #[cfg(not(bootstrap))] #[unstable(feature = "structural_match", issue = "31434")] impl StructuralEq for $t { } ) diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index bb35399323..6463668a03 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -1,5 +1,5 @@ -use crate::ptr; use crate::ops::{Deref, DerefMut}; +use crate::ptr; /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. /// @@ -63,6 +63,10 @@ impl ManuallyDrop { /// ManuallyDrop::new(Box::new(())); /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_manually_drop", since = "1.36.0"), + )] #[inline(always)] pub const fn new(value: T) -> ManuallyDrop { ManuallyDrop { value } @@ -80,6 +84,10 @@ impl ManuallyDrop { /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_manually_drop", since = "1.36.0"), + )] #[inline(always)] pub const fn into_inner(slot: ManuallyDrop) -> T { slot.value diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 792ce9dfad..670a194e2d 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -1,6 +1,10 @@ +use crate::any::type_name; +use crate::fmt; use crate::intrinsics; use crate::mem::ManuallyDrop; +// ignore-tidy-undocumented-unsafe + /// A wrapper type to construct uninitialized instances of `T`. /// /// # Initialization invariant @@ -230,6 +234,13 @@ impl Clone for MaybeUninit { } } +#[stable(feature = "maybe_uninit_debug", since = "1.41.0")] +impl fmt::Debug for MaybeUninit { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(type_name::()) + } +} + impl MaybeUninit { /// Creates a new `MaybeUninit` initialized with the given value. /// It is safe to call [`assume_init`] on the return value of this function. @@ -239,6 +250,10 @@ impl MaybeUninit { /// /// [`assume_init`]: #method.assume_init #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0"), + )] #[inline(always)] pub const fn new(val: T) -> MaybeUninit { MaybeUninit { value: ManuallyDrop::new(val) } @@ -253,11 +268,53 @@ impl MaybeUninit { /// /// [type]: union.MaybeUninit.html #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0"), + )] #[inline(always)] + #[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "maybe_uninit_uninit")] pub const fn uninit() -> MaybeUninit { MaybeUninit { uninit: () } } + /// Create a new array of `MaybeUninit` items, in an uninitialized state. + /// + /// Note: in a future Rust version this method may become unnecessary + /// when array literal syntax allows + /// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147). + /// The example below could then use `let mut buf = [MaybeUninit::::uninit(); 32];`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)] + /// + /// use std::mem::MaybeUninit; + /// + /// extern "C" { + /// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize; + /// } + /// + /// /// Returns a (possibly smaller) slice of data that was actually read + /// fn read(buf: &mut [MaybeUninit]) -> &[u8] { + /// unsafe { + /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); + /// MaybeUninit::slice_get_ref(&buf[..len]) + /// } + /// } + /// + /// let mut buf: [MaybeUninit; 32] = MaybeUninit::uninit_array(); + /// let data = read(&mut buf); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array", issue = "0")] + #[inline(always)] + pub fn uninit_array() -> [Self; LEN] { + unsafe { + MaybeUninit::<[MaybeUninit; LEN]>::uninit().assume_init() + } + } + /// A promotable constant, equivalent to `uninit()`. #[unstable(feature = "internal_uninit_const", issue = "0", reason = "hack to work around promotability")] @@ -300,6 +357,7 @@ impl MaybeUninit { /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline] + #[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "maybe_uninit_zeroed")] pub fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninit(); unsafe { @@ -440,6 +498,7 @@ impl MaybeUninit { /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] + #[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "assume_init")] pub unsafe fn assume_init(self) -> T { intrinsics::panic_if_uninhabited::(); ManuallyDrop::into_inner(self.value) @@ -509,35 +568,212 @@ impl MaybeUninit { self.as_ptr().read() } - /// Gets a reference to the contained value. + /// Gets a shared reference to the contained value. + /// + /// This can be useful when we want to access a `MaybeUninit` that has been + /// initialized but don't have ownership of the `MaybeUninit` (preventing the use + /// of `.assume_init()`). /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. + /// Calling this when the content is not yet fully initialized causes undefined + /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really + /// is in an initialized state. + /// + /// # Examples + /// + /// ### Correct usage of this method: + /// + /// ```rust + /// #![feature(maybe_uninit_ref)] + /// use std::mem::MaybeUninit; + /// + /// let mut x = MaybeUninit::>::uninit(); + /// // Initialize `x`: + /// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); } + /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to + /// // create a shared reference to it: + /// let x: &Vec = unsafe { + /// // Safety: `x` has been initialized. + /// x.get_ref() + /// }; + /// assert_eq!(x, &vec![1, 2, 3]); + /// ``` + /// + /// ### *Incorrect* usages of this method: + /// + /// ```rust,no_run + /// #![feature(maybe_uninit_ref)] + /// use std::mem::MaybeUninit; + /// + /// let x = MaybeUninit::>::uninit(); + /// let x_vec: &Vec = unsafe { x.get_ref() }; + /// // We have created a reference to an uninitialized vector! This is undefined behavior. + /// ``` + /// + /// ```rust,no_run + /// #![feature(maybe_uninit_ref)] + /// use std::{cell::Cell, mem::MaybeUninit}; + /// + /// let b = MaybeUninit::>::uninit(); + /// // Initialize the `MaybeUninit` using `Cell::set`: + /// unsafe { + /// b.get_ref().set(true); + /// // ^^^^^^^^^^^ + /// // Reference to an uninitialized `Cell`: UB! + /// } + /// ``` #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { + intrinsics::panic_if_uninhabited::(); &*self.value } - /// Gets a mutable reference to the contained value. + /// Gets a mutable (unique) reference to the contained value. + /// + /// This can be useful when we want to access a `MaybeUninit` that has been + /// initialized but don't have ownership of the `MaybeUninit` (preventing the use + /// of `.assume_init()`). /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. + /// Calling this when the content is not yet fully initialized causes undefined + /// behavior: it is up to the caller to guarantee that the `MaybeUninit` really + /// is in an initialized state. For instance, `.get_mut()` cannot be used to + /// initialize a `MaybeUninit`. + /// + /// # Examples + /// + /// ### Correct usage of this method: + /// + /// ```rust + /// #![feature(maybe_uninit_ref)] + /// use std::mem::MaybeUninit; + /// + /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] } + /// # #[cfg(FALSE)] + /// extern "C" { + /// /// Initializes *all* the bytes of the input buffer. + /// fn initialize_buffer(buf: *mut [u8; 2048]); + /// } + /// + /// let mut buf = MaybeUninit::<[u8; 2048]>::uninit(); + /// + /// // Initialize `buf`: + /// unsafe { initialize_buffer(buf.as_mut_ptr()); } + /// // Now we know that `buf` has been initialized, so we could `.assume_init()` it. + /// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes. + /// // To assert our buffer has been initialized without copying it, we upgrade + /// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`: + /// let buf: &mut [u8; 2048] = unsafe { + /// // Safety: `buf` has been initialized. + /// buf.get_mut() + /// }; + /// + /// // Now we can use `buf` as a normal slice: + /// buf.sort_unstable(); + /// assert!( + /// buf.chunks(2).all(|chunk| chunk[0] <= chunk[1]), + /// "buffer is sorted", + /// ); + /// ``` + /// + /// ### *Incorrect* usages of this method: + /// + /// You cannot use `.get_mut()` to initialize a value: + /// + /// ```rust,no_run + /// #![feature(maybe_uninit_ref)] + /// use std::mem::MaybeUninit; + /// + /// let mut b = MaybeUninit::::uninit(); + /// unsafe { + /// *b.get_mut() = true; + /// // We have created a (mutable) reference to an uninitialized `bool`! + /// // This is undefined behavior. + /// } + /// ``` + /// + /// For instance, you cannot [`Read`] into an uninitialized buffer: + /// + /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html + /// + /// ```rust,no_run + /// #![feature(maybe_uninit_ref)] + /// use std::{io, mem::MaybeUninit}; + /// + /// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]> + /// { + /// let mut buffer = MaybeUninit::<[u8; 64]>::uninit(); + /// reader.read_exact(unsafe { buffer.get_mut() })?; + /// // ^^^^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. + /// Ok(unsafe { buffer.assume_init() }) + /// } + /// ``` + /// + /// Nor can you use direct field access to do field-by-field gradual initialization: + /// + /// ```rust,no_run + /// #![feature(maybe_uninit_ref)] + /// use std::{mem::MaybeUninit, ptr}; + /// + /// struct Foo { + /// a: u32, + /// b: u8, + /// } + /// + /// let foo: Foo = unsafe { + /// let mut foo = MaybeUninit::::uninit(); + /// ptr::write(&mut foo.get_mut().a as *mut u32, 1337); + /// // ^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. + /// ptr::write(&mut foo.get_mut().b as *mut u8, 42); + /// // ^^^^^^^^^^^^^ + /// // (mutable) reference to uninitialized memory! + /// // This is undefined behavior. + /// foo.assume_init() + /// }; + /// ``` // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make // a final decision about the rules before stabilization. #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { + intrinsics::panic_if_uninhabited::(); &mut *self.value } + /// Assuming all the elements are initialized, get a slice to them. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` elements + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] + #[inline(always)] + pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] { + &*(slice as *const [Self] as *const [T]) + } + + /// Assuming all the elements are initialized, get a mutable slice to them. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` elements + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] + #[inline(always)] + pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] { + &mut *(slice as *mut [Self] as *mut [T]) + } + /// Gets a pointer to the first element of the array. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index c7da56aad3..00b32ad0b7 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -45,8 +45,9 @@ pub use crate::intrinsics::transmute; /// `mem::forget` from safe code does not fundamentally change Rust's safety /// guarantees. /// -/// That said, leaking resources such as memory or I/O objects is usually undesirable, -/// so `forget` is only recommended for specialized use cases like those shown below. +/// That said, leaking resources such as memory or I/O objects is usually undesirable. +/// The need comes up in some specialized use cases for FFI or unsafe code, but even +/// then, [`ManuallyDrop`] is typically preferred. /// /// Because forgetting a value is allowed, any `unsafe` code you write must /// allow for this possibility. You cannot return a value and expect that the @@ -68,7 +69,35 @@ pub use crate::intrinsics::transmute; /// ``` /// /// The practical use cases for `forget` are rather specialized and mainly come -/// up in unsafe or FFI code. +/// up in unsafe or FFI code. However, [`ManuallyDrop`] is usually preferred +/// for such cases, e.g.: +/// +/// ``` +/// use std::mem::ManuallyDrop; +/// +/// let v = vec![65, 122]; +/// // Before we disassemble `v` into its raw parts, make sure it +/// // does not get dropped! +/// let mut v = ManuallyDrop::new(v); +/// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak. +/// let ptr = v.as_mut_ptr(); +/// let cap = v.capacity(); +/// // Finally, build a `String`. +/// let s = unsafe { String::from_raw_parts(ptr, 2, cap) }; +/// assert_eq!(s, "Az"); +/// // `s` is implicitly dropped and its memory deallocated. +/// ``` +/// +/// Using `ManuallyDrop` here has two advantages: +/// +/// * We do not "touch" `v` after disassembling it. For some types, operations +/// such as passing ownership (to a funcion like `mem::forget`) requires them to actually +/// be fully owned right now; that is a promise we do not want to make here as we are +/// in the process of transferring ownership to the new `String` we are building. +/// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic +/// occurs before `mem::forget` was called we might end up dropping invalid data, +/// or double-dropping. In other words, `ManuallyDrop` errs on the side of leaking +/// instead of erring on the side of dropping. /// /// [drop]: fn.drop.html /// [uninit]: fn.uninitialized.html @@ -78,6 +107,7 @@ pub use crate::intrinsics::transmute; /// [leak]: ../../std/boxed/struct.Box.html#method.leak /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw /// [ub]: ../../reference/behavior-considered-undefined.html +/// [`ManuallyDrop`]: struct.ManuallyDrop.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn forget(t: T) { @@ -93,6 +123,8 @@ pub fn forget(t: T) { #[inline] #[unstable(feature = "forget_unsized", issue = "0")] pub fn forget_unsized(t: T) { + // SAFETY: the forget intrinsic could be safe, but there's no point in making it safe since + // we'll be implementing this function soon via `ManuallyDrop` unsafe { intrinsics::forget(t) } } @@ -239,6 +271,7 @@ pub fn forget_unsized(t: T) { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] +#[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_size_of", since = "1.32.0"))] pub const fn size_of() -> usize { intrinsics::size_of::() } @@ -266,7 +299,11 @@ pub const fn size_of() -> usize { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn size_of_val(val: &T) -> usize { + #[cfg(bootstrap)] + // SAFETY: going away soon unsafe { intrinsics::size_of_val(val) } + #[cfg(not(bootstrap))] + intrinsics::size_of_val(val) } /// Returns the [ABI]-required minimum alignment of a type. @@ -310,7 +347,11 @@ pub fn min_align_of() -> usize { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")] pub fn min_align_of_val(val: &T) -> usize { + #[cfg(bootstrap)] + // SAFETY: going away soon unsafe { intrinsics::min_align_of_val(val) } + #[cfg(not(bootstrap))] + intrinsics::min_align_of_val(val) } /// Returns the [ABI]-required minimum alignment of a type. @@ -331,6 +372,7 @@ pub fn min_align_of_val(val: &T) -> usize { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] +#[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_align_of", since = "1.32.0"))] pub const fn align_of() -> usize { intrinsics::min_align_of::() } @@ -350,8 +392,9 @@ pub const fn align_of() -> usize { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] pub fn align_of_val(val: &T) -> usize { - unsafe { intrinsics::min_align_of_val(val) } + min_align_of_val(val) } /// Returns `true` if dropping values of type `T` matters. @@ -412,6 +455,7 @@ pub fn align_of_val(val: &T) -> usize { /// ``` #[inline] #[stable(feature = "needs_drop", since = "1.21.0")] +#[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_needs_drop", since = "1.36.0"))] pub const fn needs_drop() -> bool { intrinsics::needs_drop::() } @@ -457,6 +501,7 @@ pub const fn needs_drop() -> bool { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] #[allow(deprecated)] +#[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "mem_zeroed")] pub unsafe fn zeroed() -> T { intrinsics::panic_if_uninhabited::(); intrinsics::init() @@ -468,7 +513,9 @@ pub unsafe fn zeroed() -> T { /// **This function is deprecated.** Use [`MaybeUninit`] instead. /// /// The reason for deprecation is that the function basically cannot be used -/// correctly: [the Rust compiler assumes][inv] that values are properly initialized. +/// correctly: it has the same effect as [`MaybeUninit::uninit().assume_init()`][uninit]. +/// As the [`assume_init` documentation][assume_init] explains, +/// [the Rust compiler assumes][inv] that values are properly initialized. /// As a consequence, calling e.g. `mem::uninitialized::()` causes immediate /// undefined behavior for returning a `bool` that is not definitely either `true` /// or `false`. Worse, truly uninitialized memory like what gets returned here @@ -479,12 +526,15 @@ pub unsafe fn zeroed() -> T { /// until they are, it is advisable to avoid them.) /// /// [`MaybeUninit`]: union.MaybeUninit.html +/// [uninit]: union.MaybeUninit.html#method.uninit +/// [assume_init]: union.MaybeUninit.html#method.assume_init /// [inv]: union.MaybeUninit.html#initialization-invariant #[inline] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] #[allow(deprecated)] +#[cfg_attr(all(not(bootstrap)), rustc_diagnostic_item = "mem_uninitialized")] pub unsafe fn uninitialized() -> T { intrinsics::panic_if_uninhabited::(); intrinsics::uninit() @@ -508,6 +558,8 @@ pub unsafe fn uninitialized() -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn swap(x: &mut T, y: &mut T) { + // SAFETY: the raw pointers have been created from safe mutable references satisfying all the + // constraints on `ptr::swap_nonoverlapping_one` unsafe { ptr::swap_nonoverlapping_one(x, y); } @@ -729,11 +781,11 @@ pub fn drop(_x: T) { } /// bar: u8, /// } /// -/// let foo_slice = [10u8]; +/// let foo_array = [10u8]; /// /// unsafe { -/// // Copy the data from 'foo_slice' and treat it as a 'Foo' -/// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice); +/// // Copy the data from 'foo_array' and treat it as a 'Foo' +/// let mut foo_struct: Foo = mem::transmute_copy(&foo_array); /// assert_eq!(foo_struct.bar, 10); /// /// // Modify the copied data @@ -741,8 +793,8 @@ pub fn drop(_x: T) { } /// assert_eq!(foo_struct.bar, 20); /// } /// -/// // The contents of 'foo_slice' should not have changed -/// assert_eq!(foo_slice, [10]); +/// // The contents of 'foo_array' should not have changed +/// assert_eq!(foo_array, [10]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -822,7 +874,11 @@ impl fmt::Debug for Discriminant { /// ``` #[stable(feature = "discriminant_value", since = "1.21.0")] pub fn discriminant(v: &T) -> Discriminant { + #[cfg(bootstrap)] + // SAFETY: going away soon unsafe { Discriminant(intrinsics::discriminant_value(v), PhantomData) } + #[cfg(not(bootstrap))] + Discriminant(intrinsics::discriminant_value(v), PhantomData) } diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs index 342ac69748..b8ddd5322a 100644 --- a/src/libcore/num/bignum.rs +++ b/src/libcore/num/bignum.rs @@ -12,13 +12,15 @@ // This module is only for dec2flt and flt2dec, and only public because of coretests. // It is not intended to ever be stabilized. #![doc(hidden)] -#![unstable(feature = "core_private_bignum", - reason = "internal routines only exposed for testing", - issue = "0")] +#![unstable( + feature = "core_private_bignum", + reason = "internal routines only exposed for testing", + issue = "0" +)] #![macro_use] -use crate::mem; use crate::intrinsics; +use crate::mem; /// Arithmetic operations required by bignums. pub trait FullOps: Sized { @@ -36,10 +38,8 @@ pub trait FullOps: Sized { /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem` /// and `0 <= rem < other`, where `W` is the number of bits in `Self`. - fn full_div_rem(self, - other: Self, - borrow: Self) - -> (Self /* quotient */, Self /* remainder */); + fn full_div_rem(self, other: Self, borrow: Self) + -> (Self /* quotient */, Self /* remainder */); } macro_rules! impl_full_ops { @@ -98,7 +98,7 @@ impl_full_ops! { const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)]; macro_rules! define_bignum { - ($name:ident: type=$ty:ty, n=$n:expr) => ( + ($name:ident: type=$ty:ty, n=$n:expr) => { /// Stack-allocated arbitrary-precision (up to certain limit) integer. /// /// This is backed by a fixed-size array of given type ("digit"). @@ -115,7 +115,7 @@ macro_rules! define_bignum { size: usize, /// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...` /// where `W` is the number of bits in the digit type. - base: [$ty; $n] + base: [$ty; $n], } impl $name { @@ -180,7 +180,7 @@ macro_rules! define_bignum { } // This could be optimized with leading_zeros() and bit shifts, but that's // probably not worth the hassle. - let digitbits = mem::size_of::<$ty>()* 8; + let digitbits = mem::size_of::<$ty>() * 8; let mut i = nonzero.len() * digitbits - 1; while self.get_bit(i) == 0 { i -= 1; @@ -272,12 +272,12 @@ macro_rules! define_bignum { let bits = bits % digitbits; assert!(digits < $n); - debug_assert!(self.base[$n-digits..].iter().all(|&v| v == 0)); - debug_assert!(bits == 0 || (self.base[$n-digits-1] >> (digitbits - bits)) == 0); + debug_assert!(self.base[$n - digits..].iter().all(|&v| v == 0)); + debug_assert!(bits == 0 || (self.base[$n - digits - 1] >> (digitbits - bits)) == 0); // shift by `digits * digitbits` bits for i in (0..self.size).rev() { - self.base[i+digits] = self.base[i]; + self.base[i + digits] = self.base[i]; } for i in 0..digits { self.base[i] = 0; @@ -287,14 +287,14 @@ macro_rules! define_bignum { let mut sz = self.size + digits; if bits > 0 { let last = sz; - let overflow = self.base[last-1] >> (digitbits - bits); + let overflow = self.base[last - 1] >> (digitbits - bits); if overflow > 0 { self.base[last] = overflow; sz += 1; } - for i in (digits+1..last).rev() { - self.base[i] = (self.base[i] << bits) | - (self.base[i-1] >> (digitbits - bits)); + for i in (digits + 1..last).rev() { + self.base[i] = + (self.base[i] << bits) | (self.base[i - 1] >> (digitbits - bits)); } self.base[digits] <<= bits; // self.base[..digits] is zero, no need to shift @@ -331,7 +331,6 @@ macro_rules! define_bignum { self } - /// Multiplies itself by a number described by `other[0] + other[1] * 2^W + /// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type) /// and returns its own mutable reference. @@ -342,7 +341,9 @@ macro_rules! define_bignum { let mut retsz = 0; for (i, &a) in aa.iter().enumerate() { - if a == 0 { continue; } + if a == 0 { + continue; + } let mut sz = bb.len(); let mut carry = 0; for (j, &b) in bb.iter().enumerate() { @@ -430,11 +431,12 @@ macro_rules! define_bignum { } impl crate::cmp::PartialEq for $name { - fn eq(&self, other: &$name) -> bool { self.base[..] == other.base[..] } + fn eq(&self, other: &$name) -> bool { + self.base[..] == other.base[..] + } } - impl crate::cmp::Eq for $name { - } + impl crate::cmp::Eq for $name {} impl crate::cmp::PartialOrd for $name { fn partial_cmp(&self, other: &$name) -> crate::option::Option { @@ -462,17 +464,17 @@ macro_rules! define_bignum { fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { use crate::mem; - let sz = if self.size < 1 {1} else {self.size}; + let sz = if self.size < 1 { 1 } else { self.size }; let digitlen = mem::size_of::<$ty>() * 2; - write!(f, "{:#x}", self.base[sz-1])?; - for &v in self.base[..sz-1].iter().rev() { + write!(f, "{:#x}", self.base[sz - 1])?; + for &v in self.base[..sz - 1].iter().rev() { write!(f, "_{:01$x}", v, digitlen)?; } crate::result::Result::Ok(()) } } - ) + }; } /// The digit type for `Big32x40`. diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index ed89852dc4..c5f6903f37 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -1,11 +1,11 @@ //! The various algorithms from the paper. use crate::cmp::min; -use crate::cmp::Ordering::{Less, Equal, Greater}; -use crate::num::diy_float::Fp; -use crate::num::dec2flt::table; -use crate::num::dec2flt::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float}; +use crate::cmp::Ordering::{Equal, Greater, Less}; use crate::num::dec2flt::num::{self, Big}; +use crate::num::dec2flt::rawfp::{self, fp_to_float, next_float, prev_float, RawFloat, Unpacked}; +use crate::num::dec2flt::table; +use crate::num::diy_float::Fp; /// Number of significand bits in Fp const P: u32 = 64; @@ -23,9 +23,9 @@ fn power_of_ten(e: i16) -> Fp { // In most architectures, floating point operations have an explicit bit size, therefore the // precision of the computation is determined on a per-operation basis. -#[cfg(any(not(target_arch="x86"), target_feature="sse2"))] +#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] mod fpu_precision { - pub fn set_precision() { } + pub fn set_precision() {} } // On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available. @@ -33,7 +33,7 @@ mod fpu_precision { // round to 80 bits causing double rounding to happen when values are eventually represented as // 32/64 bit float values. To overcome this, the FPU control word can be set so that the // computations are performed in the desired precision. -#[cfg(all(target_arch="x86", not(target_feature="sse2")))] +#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] mod fpu_precision { use crate::mem::size_of; @@ -58,6 +58,8 @@ mod fpu_precision { pub struct FPUControlWord(u16); fn set_cw(cw: u16) { + // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with + // any `u16` unsafe { asm!("fldcw $0" :: "m" (cw) :: "volatile") } } @@ -74,6 +76,8 @@ mod fpu_precision { // Get the original value of the control word to restore it later, when the // `FPUControlWord` structure is dropped + // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with + // any `u16` unsafe { asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") } // Set the control word to the desired precision. This is achieved by masking away the old diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 4536bbc94a..6fe9af8cbd 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -78,23 +78,25 @@ //! turned into {positive,negative} {zero,infinity}. #![doc(hidden)] -#![unstable(feature = "dec2flt", - reason = "internal routines only exposed for testing", - issue = "0")] +#![unstable( + feature = "dec2flt", + reason = "internal routines only exposed for testing", + issue = "0" +)] use crate::fmt; use crate::str::FromStr; -use self::parse::{parse_decimal, Decimal, Sign, ParseResult}; use self::num::digits_to_big; +use self::parse::{parse_decimal, Decimal, ParseResult, Sign}; use self::rawfp::RawFloat; mod algorithm; -mod table; mod num; +mod table; // These two have their own tests. -pub mod rawfp; pub mod parse; +pub mod rawfp; macro_rules! from_str_float_impl { ($t:ty) => { @@ -155,7 +157,7 @@ macro_rules! from_str_float_impl { dec2flt(src) } } - } + }; } from_str_float_impl!(f32); from_str_float_impl!(f64); @@ -171,7 +173,7 @@ from_str_float_impl!(f64); #[derive(Debug, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseFloatError { - kind: FloatErrorKind + kind: FloatErrorKind, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -181,10 +183,12 @@ enum FloatErrorKind { } impl ParseFloatError { - #[unstable(feature = "int_error_internals", - reason = "available through Error trait and this method should \ - not be exposed publicly", - issue = "0")] + #[unstable( + feature = "int_error_internals", + reason = "available through Error trait and this method should \ + not be exposed publicly", + issue = "0" + )] #[doc(hidden)] pub fn __description(&self) -> &str { match self.kind { @@ -222,7 +226,7 @@ fn extract_sign(s: &str) -> (Sign, &str) { /// Converts a decimal string into a floating point number. fn dec2flt(s: &str) -> Result { if s.is_empty() { - return Err(pfe_empty()) + return Err(pfe_empty()); } let (sign, s) = extract_sign(s); let flt = match parse_decimal(s) { @@ -232,8 +236,10 @@ fn dec2flt(s: &str) -> Result { ParseResult::Invalid => match s { "inf" => T::INFINITY, "NaN" => T::NAN, - _ => { return Err(pfe_invalid()); } - } + _ => { + return Err(pfe_invalid()); + } + }, }; match sign { diff --git a/src/libcore/num/dec2flt/num.rs b/src/libcore/num/dec2flt/num.rs index 4d50516ce5..208783dd32 100644 --- a/src/libcore/num/dec2flt/num.rs +++ b/src/libcore/num/dec2flt/num.rs @@ -2,7 +2,7 @@ // FIXME This module's name is a bit unfortunate, since other modules also import `core::num`. -use crate::cmp::Ordering::{self, Less, Equal, Greater}; +use crate::cmp::Ordering::{self, Equal, Greater, Less}; pub use crate::num::bignum::Big32x40 as Big; @@ -36,7 +36,10 @@ pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering { /// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and /// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is /// more complicated than this entire function. -pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 where T : IntoIterator { +pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 +where + T: IntoIterator, +{ let mut result = 0; for &c in bytes { result = result * 10 + (c - b'0') as u64; @@ -61,14 +64,9 @@ pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big { pub fn to_u64(x: &Big) -> u64 { assert!(x.bit_length() < 64); let d = x.digits(); - if d.len() < 2 { - d[0] as u64 - } else { - (d[1] as u64) << 32 | d[0] as u64 - } + if d.len() < 2 { d[0] as u64 } else { (d[1] as u64) << 32 | d[0] as u64 } } - /// Extracts a range of bits. /// Index 0 is the least significant bit and the range is half-open as usual. diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs index cf3664a874..93b08bce85 100644 --- a/src/libcore/num/dec2flt/parse.rs +++ b/src/libcore/num/dec2flt/parse.rs @@ -10,8 +10,8 @@ //! modules rely on to not panic (or overflow) in turn. //! To make matters worse, all that happens in a single pass over the input. //! So, be careful when modifying anything, and double-check with the other modules. +use self::ParseResult::{Invalid, ShortcutToInf, ShortcutToZero, Valid}; use super::num; -use self::ParseResult::{Valid, ShortcutToInf, ShortcutToZero, Invalid}; #[derive(Debug)] pub enum Sign { diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index fdbdaa238e..a127c6c3fa 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -17,15 +17,15 @@ //! Many functions in this module only handle normal numbers. The dec2flt routines conservatively //! take the universally-correct slow path (Algorithm M) for very small and very large numbers. //! That algorithm needs only next_float() which does handle subnormals and zeros. -use crate::cmp::Ordering::{Less, Equal, Greater}; +use crate::cmp::Ordering::{Equal, Greater, Less}; use crate::convert::{TryFrom, TryInto}; -use crate::ops::{Add, Mul, Div, Neg}; use crate::fmt::{Debug, LowerExp}; -use crate::num::diy_float::Fp; -use crate::num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan}; -use crate::num::FpCategory; use crate::num::dec2flt::num::{self, Big}; use crate::num::dec2flt::table; +use crate::num::diy_float::Fp; +use crate::num::FpCategory; +use crate::num::FpCategory::{Infinite, Nan, Normal, Subnormal, Zero}; +use crate::ops::{Add, Div, Mul, Neg}; #[derive(Copy, Clone, Debug)] pub struct Unpacked { @@ -44,13 +44,8 @@ impl Unpacked { /// See the parent module's doc comment for why this is necessary. /// /// Should **never ever** be implemented for other types or be used outside the dec2flt module. -pub trait RawFloat - : Copy - + Debug - + LowerExp - + Mul - + Div - + Neg +pub trait RawFloat: + Copy + Debug + LowerExp + Mul + Div + Neg { const INFINITY: Self; const NAN: Self; @@ -144,7 +139,7 @@ macro_rules! other_constants { const INFINITY: Self = $crate::$type::INFINITY; const NAN: Self = $crate::$type::NAN; const ZERO: Self = 0.0; - } + }; } impl RawFloat for f32 { @@ -163,11 +158,8 @@ impl RawFloat for f32 { let bits = self.to_bits(); let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 }; let mut exponent: i16 = ((bits >> 23) & 0xff) as i16; - let mantissa = if exponent == 0 { - (bits & 0x7fffff) << 1 - } else { - (bits & 0x7fffff) | 0x800000 - }; + let mantissa = + if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 }; // Exponent bias + mantissa shift exponent -= 127 + 23; (mantissa as u64, exponent, sign) @@ -188,12 +180,17 @@ impl RawFloat for f32 { table::F32_SHORT_POWERS[e] } - fn classify(self) -> FpCategory { self.classify() } - fn to_bits(self) -> Self::Bits { self.to_bits() } - fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) } + fn classify(self) -> FpCategory { + self.classify() + } + fn to_bits(self) -> Self::Bits { + self.to_bits() + } + fn from_bits(v: Self::Bits) -> Self { + Self::from_bits(v) + } } - impl RawFloat for f64 { type Bits = u64; @@ -235,9 +232,15 @@ impl RawFloat for f64 { table::F64_SHORT_POWERS[e] } - fn classify(self) -> FpCategory { self.classify() } - fn to_bits(self) -> Self::Bits { self.to_bits() } - fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) } + fn classify(self) -> FpCategory { + self.classify() + } + fn to_bits(self) -> Self::Bits { + self.to_bits() + } + fn from_bits(v: Self::Bits) -> Self { + Self::from_bits(v) + } } /// Converts an `Fp` to the closest machine float type. @@ -248,7 +251,7 @@ pub fn fp_to_float(x: Fp) -> T { let e = x.e + 63; if e > T::MAX_EXP { panic!("fp_to_float: exponent {} too large", e) - } else if e > T::MIN_EXP { + } else if e > T::MIN_EXP { encode_normal(round_normal::(x)) } else { panic!("fp_to_float: exponent {} too small", e) @@ -278,14 +281,15 @@ pub fn round_normal(x: Fp) -> Unpacked { /// Inverse of `RawFloat::unpack()` for normalized numbers. /// Panics if the significand or exponent are not valid for normalized numbers. pub fn encode_normal(x: Unpacked) -> T { - debug_assert!(T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG, - "encode_normal: significand not normalized"); + debug_assert!( + T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG, + "encode_normal: significand not normalized" + ); // Remove the hidden bit let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS); // Adjust the exponent for exponent bias and mantissa shift let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16; - debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP, - "encode_normal: exponent out of range"); + debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP, "encode_normal: exponent out of range"); // Leave sign bit at 0 ("+"), our numbers are all positive let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc; T::from_bits(bits.try_into().unwrap_or_else(|_| unreachable!())) @@ -315,7 +319,7 @@ pub fn big_to_fp(f: &Big) -> Fp { Equal | Greater => match leading.checked_add(1) { Some(f) => Fp { f, e }.normalize(), None => Fp { f: 1 << 63, e: e + 1 }, - } + }, } } @@ -354,8 +358,6 @@ pub fn next_float(x: T) -> T { // want, and the mantissa bits become zero. Because of the hidden bit convention, this // too is exactly what we want! // Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY. - Zero | Subnormal | Normal => { - T::from_bits(x.to_bits() + T::Bits::from(1u8)) - } + Zero | Subnormal | Normal => T::from_bits(x.to_bits() + T::Bits::from(1u8)), } } diff --git a/src/libcore/num/dec2flt/table.rs b/src/libcore/num/dec2flt/table.rs index 345ac830aa..1bd94ffa04 100644 --- a/src/libcore/num/dec2flt/table.rs +++ b/src/libcore/num/dec2flt/table.rs @@ -4,1232 +4,1237 @@ pub const MIN_E: i16 = -305; pub const MAX_E: i16 = 305; -pub const POWERS: ([u64; 611], [i16; 611]) = ([ - 0xe0b62e2929aba83c, - 0x8c71dcd9ba0b4926, - 0xaf8e5410288e1b6f, - 0xdb71e91432b1a24b, - 0x892731ac9faf056f, - 0xab70fe17c79ac6ca, - 0xd64d3d9db981787d, - 0x85f0468293f0eb4e, - 0xa76c582338ed2622, - 0xd1476e2c07286faa, - 0x82cca4db847945ca, - 0xa37fce126597973d, - 0xcc5fc196fefd7d0c, - 0xff77b1fcbebcdc4f, - 0x9faacf3df73609b1, - 0xc795830d75038c1e, - 0xf97ae3d0d2446f25, - 0x9becce62836ac577, - 0xc2e801fb244576d5, - 0xf3a20279ed56d48a, - 0x9845418c345644d7, - 0xbe5691ef416bd60c, - 0xedec366b11c6cb8f, - 0x94b3a202eb1c3f39, - 0xb9e08a83a5e34f08, - 0xe858ad248f5c22ca, - 0x91376c36d99995be, - 0xb58547448ffffb2e, - 0xe2e69915b3fff9f9, - 0x8dd01fad907ffc3c, - 0xb1442798f49ffb4b, - 0xdd95317f31c7fa1d, - 0x8a7d3eef7f1cfc52, - 0xad1c8eab5ee43b67, - 0xd863b256369d4a41, - 0x873e4f75e2224e68, - 0xa90de3535aaae202, - 0xd3515c2831559a83, - 0x8412d9991ed58092, - 0xa5178fff668ae0b6, - 0xce5d73ff402d98e4, - 0x80fa687f881c7f8e, - 0xa139029f6a239f72, - 0xc987434744ac874f, - 0xfbe9141915d7a922, - 0x9d71ac8fada6c9b5, - 0xc4ce17b399107c23, - 0xf6019da07f549b2b, - 0x99c102844f94e0fb, - 0xc0314325637a193a, - 0xf03d93eebc589f88, - 0x96267c7535b763b5, - 0xbbb01b9283253ca3, - 0xea9c227723ee8bcb, - 0x92a1958a7675175f, - 0xb749faed14125d37, - 0xe51c79a85916f485, - 0x8f31cc0937ae58d3, - 0xb2fe3f0b8599ef08, - 0xdfbdcece67006ac9, - 0x8bd6a141006042be, - 0xaecc49914078536d, - 0xda7f5bf590966849, - 0x888f99797a5e012d, - 0xaab37fd7d8f58179, - 0xd5605fcdcf32e1d7, - 0x855c3be0a17fcd26, - 0xa6b34ad8c9dfc070, - 0xd0601d8efc57b08c, - 0x823c12795db6ce57, - 0xa2cb1717b52481ed, - 0xcb7ddcdda26da269, - 0xfe5d54150b090b03, - 0x9efa548d26e5a6e2, - 0xc6b8e9b0709f109a, - 0xf867241c8cc6d4c1, - 0x9b407691d7fc44f8, - 0xc21094364dfb5637, - 0xf294b943e17a2bc4, - 0x979cf3ca6cec5b5b, - 0xbd8430bd08277231, - 0xece53cec4a314ebe, - 0x940f4613ae5ed137, - 0xb913179899f68584, - 0xe757dd7ec07426e5, - 0x9096ea6f3848984f, - 0xb4bca50b065abe63, - 0xe1ebce4dc7f16dfc, - 0x8d3360f09cf6e4bd, - 0xb080392cc4349ded, - 0xdca04777f541c568, - 0x89e42caaf9491b61, - 0xac5d37d5b79b6239, - 0xd77485cb25823ac7, - 0x86a8d39ef77164bd, - 0xa8530886b54dbdec, - 0xd267caa862a12d67, - 0x8380dea93da4bc60, - 0xa46116538d0deb78, - 0xcd795be870516656, - 0x806bd9714632dff6, - 0xa086cfcd97bf97f4, - 0xc8a883c0fdaf7df0, - 0xfad2a4b13d1b5d6c, - 0x9cc3a6eec6311a64, - 0xc3f490aa77bd60fd, - 0xf4f1b4d515acb93c, - 0x991711052d8bf3c5, - 0xbf5cd54678eef0b7, - 0xef340a98172aace5, - 0x9580869f0e7aac0f, - 0xbae0a846d2195713, - 0xe998d258869facd7, - 0x91ff83775423cc06, - 0xb67f6455292cbf08, - 0xe41f3d6a7377eeca, - 0x8e938662882af53e, - 0xb23867fb2a35b28e, - 0xdec681f9f4c31f31, - 0x8b3c113c38f9f37f, - 0xae0b158b4738705f, - 0xd98ddaee19068c76, - 0x87f8a8d4cfa417ca, - 0xa9f6d30a038d1dbc, - 0xd47487cc8470652b, - 0x84c8d4dfd2c63f3b, - 0xa5fb0a17c777cf0a, - 0xcf79cc9db955c2cc, - 0x81ac1fe293d599c0, - 0xa21727db38cb0030, - 0xca9cf1d206fdc03c, - 0xfd442e4688bd304b, - 0x9e4a9cec15763e2f, - 0xc5dd44271ad3cdba, - 0xf7549530e188c129, - 0x9a94dd3e8cf578ba, - 0xc13a148e3032d6e8, - 0xf18899b1bc3f8ca2, - 0x96f5600f15a7b7e5, - 0xbcb2b812db11a5de, - 0xebdf661791d60f56, - 0x936b9fcebb25c996, - 0xb84687c269ef3bfb, - 0xe65829b3046b0afa, - 0x8ff71a0fe2c2e6dc, - 0xb3f4e093db73a093, - 0xe0f218b8d25088b8, - 0x8c974f7383725573, - 0xafbd2350644eead0, - 0xdbac6c247d62a584, - 0x894bc396ce5da772, - 0xab9eb47c81f5114f, - 0xd686619ba27255a3, - 0x8613fd0145877586, - 0xa798fc4196e952e7, - 0xd17f3b51fca3a7a1, - 0x82ef85133de648c5, - 0xa3ab66580d5fdaf6, - 0xcc963fee10b7d1b3, - 0xffbbcfe994e5c620, - 0x9fd561f1fd0f9bd4, - 0xc7caba6e7c5382c9, - 0xf9bd690a1b68637b, - 0x9c1661a651213e2d, - 0xc31bfa0fe5698db8, - 0xf3e2f893dec3f126, - 0x986ddb5c6b3a76b8, - 0xbe89523386091466, - 0xee2ba6c0678b597f, - 0x94db483840b717f0, - 0xba121a4650e4ddec, - 0xe896a0d7e51e1566, - 0x915e2486ef32cd60, - 0xb5b5ada8aaff80b8, - 0xe3231912d5bf60e6, - 0x8df5efabc5979c90, - 0xb1736b96b6fd83b4, - 0xddd0467c64bce4a1, - 0x8aa22c0dbef60ee4, - 0xad4ab7112eb3929e, - 0xd89d64d57a607745, - 0x87625f056c7c4a8b, - 0xa93af6c6c79b5d2e, - 0xd389b47879823479, - 0x843610cb4bf160cc, - 0xa54394fe1eedb8ff, - 0xce947a3da6a9273e, - 0x811ccc668829b887, - 0xa163ff802a3426a9, - 0xc9bcff6034c13053, - 0xfc2c3f3841f17c68, - 0x9d9ba7832936edc1, - 0xc5029163f384a931, - 0xf64335bcf065d37d, - 0x99ea0196163fa42e, - 0xc06481fb9bcf8d3a, - 0xf07da27a82c37088, - 0x964e858c91ba2655, - 0xbbe226efb628afeb, - 0xeadab0aba3b2dbe5, - 0x92c8ae6b464fc96f, - 0xb77ada0617e3bbcb, - 0xe55990879ddcaabe, - 0x8f57fa54c2a9eab7, - 0xb32df8e9f3546564, - 0xdff9772470297ebd, - 0x8bfbea76c619ef36, - 0xaefae51477a06b04, - 0xdab99e59958885c5, - 0x88b402f7fd75539b, - 0xaae103b5fcd2a882, - 0xd59944a37c0752a2, - 0x857fcae62d8493a5, - 0xa6dfbd9fb8e5b88f, - 0xd097ad07a71f26b2, - 0x825ecc24c8737830, - 0xa2f67f2dfa90563b, - 0xcbb41ef979346bca, - 0xfea126b7d78186bd, - 0x9f24b832e6b0f436, - 0xc6ede63fa05d3144, - 0xf8a95fcf88747d94, - 0x9b69dbe1b548ce7d, - 0xc24452da229b021c, - 0xf2d56790ab41c2a3, - 0x97c560ba6b0919a6, - 0xbdb6b8e905cb600f, - 0xed246723473e3813, - 0x9436c0760c86e30c, - 0xb94470938fa89bcf, - 0xe7958cb87392c2c3, - 0x90bd77f3483bb9ba, - 0xb4ecd5f01a4aa828, - 0xe2280b6c20dd5232, - 0x8d590723948a535f, - 0xb0af48ec79ace837, - 0xdcdb1b2798182245, - 0x8a08f0f8bf0f156b, - 0xac8b2d36eed2dac6, - 0xd7adf884aa879177, - 0x86ccbb52ea94baeb, - 0xa87fea27a539e9a5, - 0xd29fe4b18e88640f, - 0x83a3eeeef9153e89, - 0xa48ceaaab75a8e2b, - 0xcdb02555653131b6, - 0x808e17555f3ebf12, - 0xa0b19d2ab70e6ed6, - 0xc8de047564d20a8c, - 0xfb158592be068d2f, - 0x9ced737bb6c4183d, - 0xc428d05aa4751e4d, - 0xf53304714d9265e0, - 0x993fe2c6d07b7fac, - 0xbf8fdb78849a5f97, - 0xef73d256a5c0f77d, - 0x95a8637627989aae, - 0xbb127c53b17ec159, - 0xe9d71b689dde71b0, - 0x9226712162ab070e, - 0xb6b00d69bb55c8d1, - 0xe45c10c42a2b3b06, - 0x8eb98a7a9a5b04e3, - 0xb267ed1940f1c61c, - 0xdf01e85f912e37a3, - 0x8b61313bbabce2c6, - 0xae397d8aa96c1b78, - 0xd9c7dced53c72256, - 0x881cea14545c7575, - 0xaa242499697392d3, - 0xd4ad2dbfc3d07788, - 0x84ec3c97da624ab5, - 0xa6274bbdd0fadd62, - 0xcfb11ead453994ba, - 0x81ceb32c4b43fcf5, - 0xa2425ff75e14fc32, - 0xcad2f7f5359a3b3e, - 0xfd87b5f28300ca0e, - 0x9e74d1b791e07e48, - 0xc612062576589ddb, - 0xf79687aed3eec551, - 0x9abe14cd44753b53, - 0xc16d9a0095928a27, - 0xf1c90080baf72cb1, - 0x971da05074da7bef, - 0xbce5086492111aeb, - 0xec1e4a7db69561a5, - 0x9392ee8e921d5d07, - 0xb877aa3236a4b449, - 0xe69594bec44de15b, - 0x901d7cf73ab0acd9, - 0xb424dc35095cd80f, - 0xe12e13424bb40e13, - 0x8cbccc096f5088cc, - 0xafebff0bcb24aaff, - 0xdbe6fecebdedd5bf, - 0x89705f4136b4a597, - 0xabcc77118461cefd, - 0xd6bf94d5e57a42bc, - 0x8637bd05af6c69b6, - 0xa7c5ac471b478423, - 0xd1b71758e219652c, - 0x83126e978d4fdf3b, - 0xa3d70a3d70a3d70a, - 0xcccccccccccccccd, - 0x8000000000000000, - 0xa000000000000000, - 0xc800000000000000, - 0xfa00000000000000, - 0x9c40000000000000, - 0xc350000000000000, - 0xf424000000000000, - 0x9896800000000000, - 0xbebc200000000000, - 0xee6b280000000000, - 0x9502f90000000000, - 0xba43b74000000000, - 0xe8d4a51000000000, - 0x9184e72a00000000, - 0xb5e620f480000000, - 0xe35fa931a0000000, - 0x8e1bc9bf04000000, - 0xb1a2bc2ec5000000, - 0xde0b6b3a76400000, - 0x8ac7230489e80000, - 0xad78ebc5ac620000, - 0xd8d726b7177a8000, - 0x878678326eac9000, - 0xa968163f0a57b400, - 0xd3c21bcecceda100, - 0x84595161401484a0, - 0xa56fa5b99019a5c8, - 0xcecb8f27f4200f3a, - 0x813f3978f8940984, - 0xa18f07d736b90be5, - 0xc9f2c9cd04674edf, - 0xfc6f7c4045812296, - 0x9dc5ada82b70b59e, - 0xc5371912364ce305, - 0xf684df56c3e01bc7, - 0x9a130b963a6c115c, - 0xc097ce7bc90715b3, - 0xf0bdc21abb48db20, - 0x96769950b50d88f4, - 0xbc143fa4e250eb31, - 0xeb194f8e1ae525fd, - 0x92efd1b8d0cf37be, - 0xb7abc627050305ae, - 0xe596b7b0c643c719, - 0x8f7e32ce7bea5c70, - 0xb35dbf821ae4f38c, - 0xe0352f62a19e306f, - 0x8c213d9da502de45, - 0xaf298d050e4395d7, - 0xdaf3f04651d47b4c, - 0x88d8762bf324cd10, - 0xab0e93b6efee0054, - 0xd5d238a4abe98068, - 0x85a36366eb71f041, - 0xa70c3c40a64e6c52, - 0xd0cf4b50cfe20766, - 0x82818f1281ed44a0, - 0xa321f2d7226895c8, - 0xcbea6f8ceb02bb3a, - 0xfee50b7025c36a08, - 0x9f4f2726179a2245, - 0xc722f0ef9d80aad6, - 0xf8ebad2b84e0d58c, - 0x9b934c3b330c8577, - 0xc2781f49ffcfa6d5, - 0xf316271c7fc3908b, - 0x97edd871cfda3a57, - 0xbde94e8e43d0c8ec, - 0xed63a231d4c4fb27, - 0x945e455f24fb1cf9, - 0xb975d6b6ee39e437, - 0xe7d34c64a9c85d44, - 0x90e40fbeea1d3a4b, - 0xb51d13aea4a488dd, - 0xe264589a4dcdab15, - 0x8d7eb76070a08aed, - 0xb0de65388cc8ada8, - 0xdd15fe86affad912, - 0x8a2dbf142dfcc7ab, - 0xacb92ed9397bf996, - 0xd7e77a8f87daf7fc, - 0x86f0ac99b4e8dafd, - 0xa8acd7c0222311bd, - 0xd2d80db02aabd62c, - 0x83c7088e1aab65db, - 0xa4b8cab1a1563f52, - 0xcde6fd5e09abcf27, - 0x80b05e5ac60b6178, - 0xa0dc75f1778e39d6, - 0xc913936dd571c84c, - 0xfb5878494ace3a5f, - 0x9d174b2dcec0e47b, - 0xc45d1df942711d9a, - 0xf5746577930d6501, - 0x9968bf6abbe85f20, - 0xbfc2ef456ae276e9, - 0xefb3ab16c59b14a3, - 0x95d04aee3b80ece6, - 0xbb445da9ca61281f, - 0xea1575143cf97227, - 0x924d692ca61be758, - 0xb6e0c377cfa2e12e, - 0xe498f455c38b997a, - 0x8edf98b59a373fec, - 0xb2977ee300c50fe7, - 0xdf3d5e9bc0f653e1, - 0x8b865b215899f46d, - 0xae67f1e9aec07188, - 0xda01ee641a708dea, - 0x884134fe908658b2, - 0xaa51823e34a7eedf, - 0xd4e5e2cdc1d1ea96, - 0x850fadc09923329e, - 0xa6539930bf6bff46, - 0xcfe87f7cef46ff17, - 0x81f14fae158c5f6e, - 0xa26da3999aef774a, - 0xcb090c8001ab551c, - 0xfdcb4fa002162a63, - 0x9e9f11c4014dda7e, - 0xc646d63501a1511e, - 0xf7d88bc24209a565, - 0x9ae757596946075f, - 0xc1a12d2fc3978937, - 0xf209787bb47d6b85, - 0x9745eb4d50ce6333, - 0xbd176620a501fc00, - 0xec5d3fa8ce427b00, - 0x93ba47c980e98ce0, - 0xb8a8d9bbe123f018, - 0xe6d3102ad96cec1e, - 0x9043ea1ac7e41393, - 0xb454e4a179dd1877, - 0xe16a1dc9d8545e95, - 0x8ce2529e2734bb1d, - 0xb01ae745b101e9e4, - 0xdc21a1171d42645d, - 0x899504ae72497eba, - 0xabfa45da0edbde69, - 0xd6f8d7509292d603, - 0x865b86925b9bc5c2, - 0xa7f26836f282b733, - 0xd1ef0244af2364ff, - 0x8335616aed761f1f, - 0xa402b9c5a8d3a6e7, - 0xcd036837130890a1, - 0x802221226be55a65, - 0xa02aa96b06deb0fe, - 0xc83553c5c8965d3d, - 0xfa42a8b73abbf48d, - 0x9c69a97284b578d8, - 0xc38413cf25e2d70e, - 0xf46518c2ef5b8cd1, - 0x98bf2f79d5993803, - 0xbeeefb584aff8604, - 0xeeaaba2e5dbf6785, - 0x952ab45cfa97a0b3, - 0xba756174393d88e0, - 0xe912b9d1478ceb17, - 0x91abb422ccb812ef, - 0xb616a12b7fe617aa, - 0xe39c49765fdf9d95, - 0x8e41ade9fbebc27d, - 0xb1d219647ae6b31c, - 0xde469fbd99a05fe3, - 0x8aec23d680043bee, - 0xada72ccc20054aea, - 0xd910f7ff28069da4, - 0x87aa9aff79042287, - 0xa99541bf57452b28, - 0xd3fa922f2d1675f2, - 0x847c9b5d7c2e09b7, - 0xa59bc234db398c25, - 0xcf02b2c21207ef2f, - 0x8161afb94b44f57d, - 0xa1ba1ba79e1632dc, - 0xca28a291859bbf93, - 0xfcb2cb35e702af78, - 0x9defbf01b061adab, - 0xc56baec21c7a1916, - 0xf6c69a72a3989f5c, - 0x9a3c2087a63f6399, - 0xc0cb28a98fcf3c80, - 0xf0fdf2d3f3c30b9f, - 0x969eb7c47859e744, - 0xbc4665b596706115, - 0xeb57ff22fc0c795a, - 0x9316ff75dd87cbd8, - 0xb7dcbf5354e9bece, - 0xe5d3ef282a242e82, - 0x8fa475791a569d11, - 0xb38d92d760ec4455, - 0xe070f78d3927556b, - 0x8c469ab843b89563, - 0xaf58416654a6babb, - 0xdb2e51bfe9d0696a, - 0x88fcf317f22241e2, - 0xab3c2fddeeaad25b, - 0xd60b3bd56a5586f2, - 0x85c7056562757457, - 0xa738c6bebb12d16d, - 0xd106f86e69d785c8, - 0x82a45b450226b39d, - 0xa34d721642b06084, - 0xcc20ce9bd35c78a5, - 0xff290242c83396ce, - 0x9f79a169bd203e41, - 0xc75809c42c684dd1, - 0xf92e0c3537826146, - 0x9bbcc7a142b17ccc, - 0xc2abf989935ddbfe, - 0xf356f7ebf83552fe, - 0x98165af37b2153df, - 0xbe1bf1b059e9a8d6, - 0xeda2ee1c7064130c, - 0x9485d4d1c63e8be8, - 0xb9a74a0637ce2ee1, - 0xe8111c87c5c1ba9a, - 0x910ab1d4db9914a0, - 0xb54d5e4a127f59c8, - 0xe2a0b5dc971f303a, - 0x8da471a9de737e24, - 0xb10d8e1456105dad, - 0xdd50f1996b947519, - 0x8a5296ffe33cc930, - 0xace73cbfdc0bfb7b, - 0xd8210befd30efa5a, - 0x8714a775e3e95c78, - 0xa8d9d1535ce3b396, - 0xd31045a8341ca07c, - 0x83ea2b892091e44e, - 0xa4e4b66b68b65d61, - 0xce1de40642e3f4b9, - 0x80d2ae83e9ce78f4, - 0xa1075a24e4421731, - 0xc94930ae1d529cfd, - 0xfb9b7cd9a4a7443c, - 0x9d412e0806e88aa6, - 0xc491798a08a2ad4f, - 0xf5b5d7ec8acb58a3, - 0x9991a6f3d6bf1766, - 0xbff610b0cc6edd3f, - 0xeff394dcff8a948f, - 0x95f83d0a1fb69cd9, - 0xbb764c4ca7a44410, - 0xea53df5fd18d5514, - 0x92746b9be2f8552c, - 0xb7118682dbb66a77, - 0xe4d5e82392a40515, - 0x8f05b1163ba6832d, - 0xb2c71d5bca9023f8, - 0xdf78e4b2bd342cf7, - 0x8bab8eefb6409c1a, - 0xae9672aba3d0c321, - 0xda3c0f568cc4f3e9, - 0x8865899617fb1871, - 0xaa7eebfb9df9de8e, - 0xd51ea6fa85785631, - 0x8533285c936b35df, - 0xa67ff273b8460357, - 0xd01fef10a657842c, - 0x8213f56a67f6b29c, - 0xa298f2c501f45f43, - 0xcb3f2f7642717713, - 0xfe0efb53d30dd4d8, - 0x9ec95d1463e8a507, - 0xc67bb4597ce2ce49, - 0xf81aa16fdc1b81db, - 0x9b10a4e5e9913129, - 0xc1d4ce1f63f57d73, - 0xf24a01a73cf2dcd0, - 0x976e41088617ca02, - 0xbd49d14aa79dbc82, - 0xec9c459d51852ba3, - 0x93e1ab8252f33b46, - 0xb8da1662e7b00a17, - 0xe7109bfba19c0c9d, - 0x906a617d450187e2, - 0xb484f9dc9641e9db, - 0xe1a63853bbd26451, - 0x8d07e33455637eb3, - 0xb049dc016abc5e60, - 0xdc5c5301c56b75f7, - 0x89b9b3e11b6329bb, - 0xac2820d9623bf429, - 0xd732290fbacaf134, - 0x867f59a9d4bed6c0, - 0xa81f301449ee8c70, - 0xd226fc195c6a2f8c, - 0x83585d8fd9c25db8, - 0xa42e74f3d032f526, - 0xcd3a1230c43fb26f, - 0x80444b5e7aa7cf85, - 0xa0555e361951c367, - 0xc86ab5c39fa63441, - 0xfa856334878fc151, - 0x9c935e00d4b9d8d2, - 0xc3b8358109e84f07, - 0xf4a642e14c6262c9, - 0x98e7e9cccfbd7dbe, - 0xbf21e44003acdd2d, - 0xeeea5d5004981478, - 0x95527a5202df0ccb, - 0xbaa718e68396cffe, - 0xe950df20247c83fd, - 0x91d28b7416cdd27e, -], [ - -1077, - -1073, - -1070, - -1067, - -1063, - -1060, - -1057, - -1053, - -1050, - -1047, - -1043, - -1040, - -1037, - -1034, - -1030, - -1027, - -1024, - -1020, - -1017, - -1014, - -1010, - -1007, - -1004, - -1000, - -997, - -994, - -990, - -987, - -984, - -980, - -977, - -974, - -970, - -967, - -964, - -960, - -957, - -954, - -950, - -947, - -944, - -940, - -937, - -934, - -931, - -927, - -924, - -921, - -917, - -914, - -911, - -907, - -904, - -901, - -897, - -894, - -891, - -887, - -884, - -881, - -877, - -874, - -871, - -867, - -864, - -861, - -857, - -854, - -851, - -847, - -844, - -841, - -838, - -834, - -831, - -828, - -824, - -821, - -818, - -814, - -811, - -808, - -804, - -801, - -798, - -794, - -791, - -788, - -784, - -781, - -778, - -774, - -771, - -768, - -764, - -761, - -758, - -754, - -751, - -748, - -744, - -741, - -738, - -735, - -731, - -728, - -725, - -721, - -718, - -715, - -711, - -708, - -705, - -701, - -698, - -695, - -691, - -688, - -685, - -681, - -678, - -675, - -671, - -668, - -665, - -661, - -658, - -655, - -651, - -648, - -645, - -642, - -638, - -635, - -632, - -628, - -625, - -622, - -618, - -615, - -612, - -608, - -605, - -602, - -598, - -595, - -592, - -588, - -585, - -582, - -578, - -575, - -572, - -568, - -565, - -562, - -558, - -555, - -552, - -549, - -545, - -542, - -539, - -535, - -532, - -529, - -525, - -522, - -519, - -515, - -512, - -509, - -505, - -502, - -499, - -495, - -492, - -489, - -485, - -482, - -479, - -475, - -472, - -469, - -465, - -462, - -459, - -455, - -452, - -449, - -446, - -442, - -439, - -436, - -432, - -429, - -426, - -422, - -419, - -416, - -412, - -409, - -406, - -402, - -399, - -396, - -392, - -389, - -386, - -382, - -379, - -376, - -372, - -369, - -366, - -362, - -359, - -356, - -353, - -349, - -346, - -343, - -339, - -336, - -333, - -329, - -326, - -323, - -319, - -316, - -313, - -309, - -306, - -303, - -299, - -296, - -293, - -289, - -286, - -283, - -279, - -276, - -273, - -269, - -266, - -263, - -259, - -256, - -253, - -250, - -246, - -243, - -240, - -236, - -233, - -230, - -226, - -223, - -220, - -216, - -213, - -210, - -206, - -203, - -200, - -196, - -193, - -190, - -186, - -183, - -180, - -176, - -173, - -170, - -166, - -163, - -160, - -157, - -153, - -150, - -147, - -143, - -140, - -137, - -133, - -130, - -127, - -123, - -120, - -117, - -113, - -110, - -107, - -103, - -100, - -97, - -93, - -90, - -87, - -83, - -80, - -77, - -73, - -70, - -67, - -63, - -60, - -57, - -54, - -50, - -47, - -44, - -40, - -37, - -34, - -30, - -27, - -24, - -20, - -17, - -14, - -10, - -7, - -4, - 0, - 3, - 6, - 10, - 13, - 16, - 20, - 23, - 26, - 30, - 33, - 36, - 39, - 43, - 46, - 49, - 53, - 56, - 59, - 63, - 66, - 69, - 73, - 76, - 79, - 83, - 86, - 89, - 93, - 96, - 99, - 103, - 106, - 109, - 113, - 116, - 119, - 123, - 126, - 129, - 132, - 136, - 139, - 142, - 146, - 149, - 152, - 156, - 159, - 162, - 166, - 169, - 172, - 176, - 179, - 182, - 186, - 189, - 192, - 196, - 199, - 202, - 206, - 209, - 212, - 216, - 219, - 222, - 226, - 229, - 232, - 235, - 239, - 242, - 245, - 249, - 252, - 255, - 259, - 262, - 265, - 269, - 272, - 275, - 279, - 282, - 285, - 289, - 292, - 295, - 299, - 302, - 305, - 309, - 312, - 315, - 319, - 322, - 325, - 328, - 332, - 335, - 338, - 342, - 345, - 348, - 352, - 355, - 358, - 362, - 365, - 368, - 372, - 375, - 378, - 382, - 385, - 388, - 392, - 395, - 398, - 402, - 405, - 408, - 412, - 415, - 418, - 422, - 425, - 428, - 431, - 435, - 438, - 441, - 445, - 448, - 451, - 455, - 458, - 461, - 465, - 468, - 471, - 475, - 478, - 481, - 485, - 488, - 491, - 495, - 498, - 501, - 505, - 508, - 511, - 515, - 518, - 521, - 524, - 528, - 531, - 534, - 538, - 541, - 544, - 548, - 551, - 554, - 558, - 561, - 564, - 568, - 571, - 574, - 578, - 581, - 584, - 588, - 591, - 594, - 598, - 601, - 604, - 608, - 611, - 614, - 617, - 621, - 624, - 627, - 631, - 634, - 637, - 641, - 644, - 647, - 651, - 654, - 657, - 661, - 664, - 667, - 671, - 674, - 677, - 681, - 684, - 687, - 691, - 694, - 697, - 701, - 704, - 707, - 711, - 714, - 717, - 720, - 724, - 727, - 730, - 734, - 737, - 740, - 744, - 747, - 750, - 754, - 757, - 760, - 764, - 767, - 770, - 774, - 777, - 780, - 784, - 787, - 790, - 794, - 797, - 800, - 804, - 807, - 810, - 813, - 817, - 820, - 823, - 827, - 830, - 833, - 837, - 840, - 843, - 847, - 850, - 853, - 857, - 860, - 863, - 867, - 870, - 873, - 877, - 880, - 883, - 887, - 890, - 893, - 897, - 900, - 903, - 907, - 910, - 913, - 916, - 920, - 923, - 926, - 930, - 933, - 936, - 940, - 943, - 946, - 950, -]); +#[rustfmt::skip] +pub const POWERS: ([u64; 611], [i16; 611]) = ( + [ + 0xe0b62e2929aba83c, + 0x8c71dcd9ba0b4926, + 0xaf8e5410288e1b6f, + 0xdb71e91432b1a24b, + 0x892731ac9faf056f, + 0xab70fe17c79ac6ca, + 0xd64d3d9db981787d, + 0x85f0468293f0eb4e, + 0xa76c582338ed2622, + 0xd1476e2c07286faa, + 0x82cca4db847945ca, + 0xa37fce126597973d, + 0xcc5fc196fefd7d0c, + 0xff77b1fcbebcdc4f, + 0x9faacf3df73609b1, + 0xc795830d75038c1e, + 0xf97ae3d0d2446f25, + 0x9becce62836ac577, + 0xc2e801fb244576d5, + 0xf3a20279ed56d48a, + 0x9845418c345644d7, + 0xbe5691ef416bd60c, + 0xedec366b11c6cb8f, + 0x94b3a202eb1c3f39, + 0xb9e08a83a5e34f08, + 0xe858ad248f5c22ca, + 0x91376c36d99995be, + 0xb58547448ffffb2e, + 0xe2e69915b3fff9f9, + 0x8dd01fad907ffc3c, + 0xb1442798f49ffb4b, + 0xdd95317f31c7fa1d, + 0x8a7d3eef7f1cfc52, + 0xad1c8eab5ee43b67, + 0xd863b256369d4a41, + 0x873e4f75e2224e68, + 0xa90de3535aaae202, + 0xd3515c2831559a83, + 0x8412d9991ed58092, + 0xa5178fff668ae0b6, + 0xce5d73ff402d98e4, + 0x80fa687f881c7f8e, + 0xa139029f6a239f72, + 0xc987434744ac874f, + 0xfbe9141915d7a922, + 0x9d71ac8fada6c9b5, + 0xc4ce17b399107c23, + 0xf6019da07f549b2b, + 0x99c102844f94e0fb, + 0xc0314325637a193a, + 0xf03d93eebc589f88, + 0x96267c7535b763b5, + 0xbbb01b9283253ca3, + 0xea9c227723ee8bcb, + 0x92a1958a7675175f, + 0xb749faed14125d37, + 0xe51c79a85916f485, + 0x8f31cc0937ae58d3, + 0xb2fe3f0b8599ef08, + 0xdfbdcece67006ac9, + 0x8bd6a141006042be, + 0xaecc49914078536d, + 0xda7f5bf590966849, + 0x888f99797a5e012d, + 0xaab37fd7d8f58179, + 0xd5605fcdcf32e1d7, + 0x855c3be0a17fcd26, + 0xa6b34ad8c9dfc070, + 0xd0601d8efc57b08c, + 0x823c12795db6ce57, + 0xa2cb1717b52481ed, + 0xcb7ddcdda26da269, + 0xfe5d54150b090b03, + 0x9efa548d26e5a6e2, + 0xc6b8e9b0709f109a, + 0xf867241c8cc6d4c1, + 0x9b407691d7fc44f8, + 0xc21094364dfb5637, + 0xf294b943e17a2bc4, + 0x979cf3ca6cec5b5b, + 0xbd8430bd08277231, + 0xece53cec4a314ebe, + 0x940f4613ae5ed137, + 0xb913179899f68584, + 0xe757dd7ec07426e5, + 0x9096ea6f3848984f, + 0xb4bca50b065abe63, + 0xe1ebce4dc7f16dfc, + 0x8d3360f09cf6e4bd, + 0xb080392cc4349ded, + 0xdca04777f541c568, + 0x89e42caaf9491b61, + 0xac5d37d5b79b6239, + 0xd77485cb25823ac7, + 0x86a8d39ef77164bd, + 0xa8530886b54dbdec, + 0xd267caa862a12d67, + 0x8380dea93da4bc60, + 0xa46116538d0deb78, + 0xcd795be870516656, + 0x806bd9714632dff6, + 0xa086cfcd97bf97f4, + 0xc8a883c0fdaf7df0, + 0xfad2a4b13d1b5d6c, + 0x9cc3a6eec6311a64, + 0xc3f490aa77bd60fd, + 0xf4f1b4d515acb93c, + 0x991711052d8bf3c5, + 0xbf5cd54678eef0b7, + 0xef340a98172aace5, + 0x9580869f0e7aac0f, + 0xbae0a846d2195713, + 0xe998d258869facd7, + 0x91ff83775423cc06, + 0xb67f6455292cbf08, + 0xe41f3d6a7377eeca, + 0x8e938662882af53e, + 0xb23867fb2a35b28e, + 0xdec681f9f4c31f31, + 0x8b3c113c38f9f37f, + 0xae0b158b4738705f, + 0xd98ddaee19068c76, + 0x87f8a8d4cfa417ca, + 0xa9f6d30a038d1dbc, + 0xd47487cc8470652b, + 0x84c8d4dfd2c63f3b, + 0xa5fb0a17c777cf0a, + 0xcf79cc9db955c2cc, + 0x81ac1fe293d599c0, + 0xa21727db38cb0030, + 0xca9cf1d206fdc03c, + 0xfd442e4688bd304b, + 0x9e4a9cec15763e2f, + 0xc5dd44271ad3cdba, + 0xf7549530e188c129, + 0x9a94dd3e8cf578ba, + 0xc13a148e3032d6e8, + 0xf18899b1bc3f8ca2, + 0x96f5600f15a7b7e5, + 0xbcb2b812db11a5de, + 0xebdf661791d60f56, + 0x936b9fcebb25c996, + 0xb84687c269ef3bfb, + 0xe65829b3046b0afa, + 0x8ff71a0fe2c2e6dc, + 0xb3f4e093db73a093, + 0xe0f218b8d25088b8, + 0x8c974f7383725573, + 0xafbd2350644eead0, + 0xdbac6c247d62a584, + 0x894bc396ce5da772, + 0xab9eb47c81f5114f, + 0xd686619ba27255a3, + 0x8613fd0145877586, + 0xa798fc4196e952e7, + 0xd17f3b51fca3a7a1, + 0x82ef85133de648c5, + 0xa3ab66580d5fdaf6, + 0xcc963fee10b7d1b3, + 0xffbbcfe994e5c620, + 0x9fd561f1fd0f9bd4, + 0xc7caba6e7c5382c9, + 0xf9bd690a1b68637b, + 0x9c1661a651213e2d, + 0xc31bfa0fe5698db8, + 0xf3e2f893dec3f126, + 0x986ddb5c6b3a76b8, + 0xbe89523386091466, + 0xee2ba6c0678b597f, + 0x94db483840b717f0, + 0xba121a4650e4ddec, + 0xe896a0d7e51e1566, + 0x915e2486ef32cd60, + 0xb5b5ada8aaff80b8, + 0xe3231912d5bf60e6, + 0x8df5efabc5979c90, + 0xb1736b96b6fd83b4, + 0xddd0467c64bce4a1, + 0x8aa22c0dbef60ee4, + 0xad4ab7112eb3929e, + 0xd89d64d57a607745, + 0x87625f056c7c4a8b, + 0xa93af6c6c79b5d2e, + 0xd389b47879823479, + 0x843610cb4bf160cc, + 0xa54394fe1eedb8ff, + 0xce947a3da6a9273e, + 0x811ccc668829b887, + 0xa163ff802a3426a9, + 0xc9bcff6034c13053, + 0xfc2c3f3841f17c68, + 0x9d9ba7832936edc1, + 0xc5029163f384a931, + 0xf64335bcf065d37d, + 0x99ea0196163fa42e, + 0xc06481fb9bcf8d3a, + 0xf07da27a82c37088, + 0x964e858c91ba2655, + 0xbbe226efb628afeb, + 0xeadab0aba3b2dbe5, + 0x92c8ae6b464fc96f, + 0xb77ada0617e3bbcb, + 0xe55990879ddcaabe, + 0x8f57fa54c2a9eab7, + 0xb32df8e9f3546564, + 0xdff9772470297ebd, + 0x8bfbea76c619ef36, + 0xaefae51477a06b04, + 0xdab99e59958885c5, + 0x88b402f7fd75539b, + 0xaae103b5fcd2a882, + 0xd59944a37c0752a2, + 0x857fcae62d8493a5, + 0xa6dfbd9fb8e5b88f, + 0xd097ad07a71f26b2, + 0x825ecc24c8737830, + 0xa2f67f2dfa90563b, + 0xcbb41ef979346bca, + 0xfea126b7d78186bd, + 0x9f24b832e6b0f436, + 0xc6ede63fa05d3144, + 0xf8a95fcf88747d94, + 0x9b69dbe1b548ce7d, + 0xc24452da229b021c, + 0xf2d56790ab41c2a3, + 0x97c560ba6b0919a6, + 0xbdb6b8e905cb600f, + 0xed246723473e3813, + 0x9436c0760c86e30c, + 0xb94470938fa89bcf, + 0xe7958cb87392c2c3, + 0x90bd77f3483bb9ba, + 0xb4ecd5f01a4aa828, + 0xe2280b6c20dd5232, + 0x8d590723948a535f, + 0xb0af48ec79ace837, + 0xdcdb1b2798182245, + 0x8a08f0f8bf0f156b, + 0xac8b2d36eed2dac6, + 0xd7adf884aa879177, + 0x86ccbb52ea94baeb, + 0xa87fea27a539e9a5, + 0xd29fe4b18e88640f, + 0x83a3eeeef9153e89, + 0xa48ceaaab75a8e2b, + 0xcdb02555653131b6, + 0x808e17555f3ebf12, + 0xa0b19d2ab70e6ed6, + 0xc8de047564d20a8c, + 0xfb158592be068d2f, + 0x9ced737bb6c4183d, + 0xc428d05aa4751e4d, + 0xf53304714d9265e0, + 0x993fe2c6d07b7fac, + 0xbf8fdb78849a5f97, + 0xef73d256a5c0f77d, + 0x95a8637627989aae, + 0xbb127c53b17ec159, + 0xe9d71b689dde71b0, + 0x9226712162ab070e, + 0xb6b00d69bb55c8d1, + 0xe45c10c42a2b3b06, + 0x8eb98a7a9a5b04e3, + 0xb267ed1940f1c61c, + 0xdf01e85f912e37a3, + 0x8b61313bbabce2c6, + 0xae397d8aa96c1b78, + 0xd9c7dced53c72256, + 0x881cea14545c7575, + 0xaa242499697392d3, + 0xd4ad2dbfc3d07788, + 0x84ec3c97da624ab5, + 0xa6274bbdd0fadd62, + 0xcfb11ead453994ba, + 0x81ceb32c4b43fcf5, + 0xa2425ff75e14fc32, + 0xcad2f7f5359a3b3e, + 0xfd87b5f28300ca0e, + 0x9e74d1b791e07e48, + 0xc612062576589ddb, + 0xf79687aed3eec551, + 0x9abe14cd44753b53, + 0xc16d9a0095928a27, + 0xf1c90080baf72cb1, + 0x971da05074da7bef, + 0xbce5086492111aeb, + 0xec1e4a7db69561a5, + 0x9392ee8e921d5d07, + 0xb877aa3236a4b449, + 0xe69594bec44de15b, + 0x901d7cf73ab0acd9, + 0xb424dc35095cd80f, + 0xe12e13424bb40e13, + 0x8cbccc096f5088cc, + 0xafebff0bcb24aaff, + 0xdbe6fecebdedd5bf, + 0x89705f4136b4a597, + 0xabcc77118461cefd, + 0xd6bf94d5e57a42bc, + 0x8637bd05af6c69b6, + 0xa7c5ac471b478423, + 0xd1b71758e219652c, + 0x83126e978d4fdf3b, + 0xa3d70a3d70a3d70a, + 0xcccccccccccccccd, + 0x8000000000000000, + 0xa000000000000000, + 0xc800000000000000, + 0xfa00000000000000, + 0x9c40000000000000, + 0xc350000000000000, + 0xf424000000000000, + 0x9896800000000000, + 0xbebc200000000000, + 0xee6b280000000000, + 0x9502f90000000000, + 0xba43b74000000000, + 0xe8d4a51000000000, + 0x9184e72a00000000, + 0xb5e620f480000000, + 0xe35fa931a0000000, + 0x8e1bc9bf04000000, + 0xb1a2bc2ec5000000, + 0xde0b6b3a76400000, + 0x8ac7230489e80000, + 0xad78ebc5ac620000, + 0xd8d726b7177a8000, + 0x878678326eac9000, + 0xa968163f0a57b400, + 0xd3c21bcecceda100, + 0x84595161401484a0, + 0xa56fa5b99019a5c8, + 0xcecb8f27f4200f3a, + 0x813f3978f8940984, + 0xa18f07d736b90be5, + 0xc9f2c9cd04674edf, + 0xfc6f7c4045812296, + 0x9dc5ada82b70b59e, + 0xc5371912364ce305, + 0xf684df56c3e01bc7, + 0x9a130b963a6c115c, + 0xc097ce7bc90715b3, + 0xf0bdc21abb48db20, + 0x96769950b50d88f4, + 0xbc143fa4e250eb31, + 0xeb194f8e1ae525fd, + 0x92efd1b8d0cf37be, + 0xb7abc627050305ae, + 0xe596b7b0c643c719, + 0x8f7e32ce7bea5c70, + 0xb35dbf821ae4f38c, + 0xe0352f62a19e306f, + 0x8c213d9da502de45, + 0xaf298d050e4395d7, + 0xdaf3f04651d47b4c, + 0x88d8762bf324cd10, + 0xab0e93b6efee0054, + 0xd5d238a4abe98068, + 0x85a36366eb71f041, + 0xa70c3c40a64e6c52, + 0xd0cf4b50cfe20766, + 0x82818f1281ed44a0, + 0xa321f2d7226895c8, + 0xcbea6f8ceb02bb3a, + 0xfee50b7025c36a08, + 0x9f4f2726179a2245, + 0xc722f0ef9d80aad6, + 0xf8ebad2b84e0d58c, + 0x9b934c3b330c8577, + 0xc2781f49ffcfa6d5, + 0xf316271c7fc3908b, + 0x97edd871cfda3a57, + 0xbde94e8e43d0c8ec, + 0xed63a231d4c4fb27, + 0x945e455f24fb1cf9, + 0xb975d6b6ee39e437, + 0xe7d34c64a9c85d44, + 0x90e40fbeea1d3a4b, + 0xb51d13aea4a488dd, + 0xe264589a4dcdab15, + 0x8d7eb76070a08aed, + 0xb0de65388cc8ada8, + 0xdd15fe86affad912, + 0x8a2dbf142dfcc7ab, + 0xacb92ed9397bf996, + 0xd7e77a8f87daf7fc, + 0x86f0ac99b4e8dafd, + 0xa8acd7c0222311bd, + 0xd2d80db02aabd62c, + 0x83c7088e1aab65db, + 0xa4b8cab1a1563f52, + 0xcde6fd5e09abcf27, + 0x80b05e5ac60b6178, + 0xa0dc75f1778e39d6, + 0xc913936dd571c84c, + 0xfb5878494ace3a5f, + 0x9d174b2dcec0e47b, + 0xc45d1df942711d9a, + 0xf5746577930d6501, + 0x9968bf6abbe85f20, + 0xbfc2ef456ae276e9, + 0xefb3ab16c59b14a3, + 0x95d04aee3b80ece6, + 0xbb445da9ca61281f, + 0xea1575143cf97227, + 0x924d692ca61be758, + 0xb6e0c377cfa2e12e, + 0xe498f455c38b997a, + 0x8edf98b59a373fec, + 0xb2977ee300c50fe7, + 0xdf3d5e9bc0f653e1, + 0x8b865b215899f46d, + 0xae67f1e9aec07188, + 0xda01ee641a708dea, + 0x884134fe908658b2, + 0xaa51823e34a7eedf, + 0xd4e5e2cdc1d1ea96, + 0x850fadc09923329e, + 0xa6539930bf6bff46, + 0xcfe87f7cef46ff17, + 0x81f14fae158c5f6e, + 0xa26da3999aef774a, + 0xcb090c8001ab551c, + 0xfdcb4fa002162a63, + 0x9e9f11c4014dda7e, + 0xc646d63501a1511e, + 0xf7d88bc24209a565, + 0x9ae757596946075f, + 0xc1a12d2fc3978937, + 0xf209787bb47d6b85, + 0x9745eb4d50ce6333, + 0xbd176620a501fc00, + 0xec5d3fa8ce427b00, + 0x93ba47c980e98ce0, + 0xb8a8d9bbe123f018, + 0xe6d3102ad96cec1e, + 0x9043ea1ac7e41393, + 0xb454e4a179dd1877, + 0xe16a1dc9d8545e95, + 0x8ce2529e2734bb1d, + 0xb01ae745b101e9e4, + 0xdc21a1171d42645d, + 0x899504ae72497eba, + 0xabfa45da0edbde69, + 0xd6f8d7509292d603, + 0x865b86925b9bc5c2, + 0xa7f26836f282b733, + 0xd1ef0244af2364ff, + 0x8335616aed761f1f, + 0xa402b9c5a8d3a6e7, + 0xcd036837130890a1, + 0x802221226be55a65, + 0xa02aa96b06deb0fe, + 0xc83553c5c8965d3d, + 0xfa42a8b73abbf48d, + 0x9c69a97284b578d8, + 0xc38413cf25e2d70e, + 0xf46518c2ef5b8cd1, + 0x98bf2f79d5993803, + 0xbeeefb584aff8604, + 0xeeaaba2e5dbf6785, + 0x952ab45cfa97a0b3, + 0xba756174393d88e0, + 0xe912b9d1478ceb17, + 0x91abb422ccb812ef, + 0xb616a12b7fe617aa, + 0xe39c49765fdf9d95, + 0x8e41ade9fbebc27d, + 0xb1d219647ae6b31c, + 0xde469fbd99a05fe3, + 0x8aec23d680043bee, + 0xada72ccc20054aea, + 0xd910f7ff28069da4, + 0x87aa9aff79042287, + 0xa99541bf57452b28, + 0xd3fa922f2d1675f2, + 0x847c9b5d7c2e09b7, + 0xa59bc234db398c25, + 0xcf02b2c21207ef2f, + 0x8161afb94b44f57d, + 0xa1ba1ba79e1632dc, + 0xca28a291859bbf93, + 0xfcb2cb35e702af78, + 0x9defbf01b061adab, + 0xc56baec21c7a1916, + 0xf6c69a72a3989f5c, + 0x9a3c2087a63f6399, + 0xc0cb28a98fcf3c80, + 0xf0fdf2d3f3c30b9f, + 0x969eb7c47859e744, + 0xbc4665b596706115, + 0xeb57ff22fc0c795a, + 0x9316ff75dd87cbd8, + 0xb7dcbf5354e9bece, + 0xe5d3ef282a242e82, + 0x8fa475791a569d11, + 0xb38d92d760ec4455, + 0xe070f78d3927556b, + 0x8c469ab843b89563, + 0xaf58416654a6babb, + 0xdb2e51bfe9d0696a, + 0x88fcf317f22241e2, + 0xab3c2fddeeaad25b, + 0xd60b3bd56a5586f2, + 0x85c7056562757457, + 0xa738c6bebb12d16d, + 0xd106f86e69d785c8, + 0x82a45b450226b39d, + 0xa34d721642b06084, + 0xcc20ce9bd35c78a5, + 0xff290242c83396ce, + 0x9f79a169bd203e41, + 0xc75809c42c684dd1, + 0xf92e0c3537826146, + 0x9bbcc7a142b17ccc, + 0xc2abf989935ddbfe, + 0xf356f7ebf83552fe, + 0x98165af37b2153df, + 0xbe1bf1b059e9a8d6, + 0xeda2ee1c7064130c, + 0x9485d4d1c63e8be8, + 0xb9a74a0637ce2ee1, + 0xe8111c87c5c1ba9a, + 0x910ab1d4db9914a0, + 0xb54d5e4a127f59c8, + 0xe2a0b5dc971f303a, + 0x8da471a9de737e24, + 0xb10d8e1456105dad, + 0xdd50f1996b947519, + 0x8a5296ffe33cc930, + 0xace73cbfdc0bfb7b, + 0xd8210befd30efa5a, + 0x8714a775e3e95c78, + 0xa8d9d1535ce3b396, + 0xd31045a8341ca07c, + 0x83ea2b892091e44e, + 0xa4e4b66b68b65d61, + 0xce1de40642e3f4b9, + 0x80d2ae83e9ce78f4, + 0xa1075a24e4421731, + 0xc94930ae1d529cfd, + 0xfb9b7cd9a4a7443c, + 0x9d412e0806e88aa6, + 0xc491798a08a2ad4f, + 0xf5b5d7ec8acb58a3, + 0x9991a6f3d6bf1766, + 0xbff610b0cc6edd3f, + 0xeff394dcff8a948f, + 0x95f83d0a1fb69cd9, + 0xbb764c4ca7a44410, + 0xea53df5fd18d5514, + 0x92746b9be2f8552c, + 0xb7118682dbb66a77, + 0xe4d5e82392a40515, + 0x8f05b1163ba6832d, + 0xb2c71d5bca9023f8, + 0xdf78e4b2bd342cf7, + 0x8bab8eefb6409c1a, + 0xae9672aba3d0c321, + 0xda3c0f568cc4f3e9, + 0x8865899617fb1871, + 0xaa7eebfb9df9de8e, + 0xd51ea6fa85785631, + 0x8533285c936b35df, + 0xa67ff273b8460357, + 0xd01fef10a657842c, + 0x8213f56a67f6b29c, + 0xa298f2c501f45f43, + 0xcb3f2f7642717713, + 0xfe0efb53d30dd4d8, + 0x9ec95d1463e8a507, + 0xc67bb4597ce2ce49, + 0xf81aa16fdc1b81db, + 0x9b10a4e5e9913129, + 0xc1d4ce1f63f57d73, + 0xf24a01a73cf2dcd0, + 0x976e41088617ca02, + 0xbd49d14aa79dbc82, + 0xec9c459d51852ba3, + 0x93e1ab8252f33b46, + 0xb8da1662e7b00a17, + 0xe7109bfba19c0c9d, + 0x906a617d450187e2, + 0xb484f9dc9641e9db, + 0xe1a63853bbd26451, + 0x8d07e33455637eb3, + 0xb049dc016abc5e60, + 0xdc5c5301c56b75f7, + 0x89b9b3e11b6329bb, + 0xac2820d9623bf429, + 0xd732290fbacaf134, + 0x867f59a9d4bed6c0, + 0xa81f301449ee8c70, + 0xd226fc195c6a2f8c, + 0x83585d8fd9c25db8, + 0xa42e74f3d032f526, + 0xcd3a1230c43fb26f, + 0x80444b5e7aa7cf85, + 0xa0555e361951c367, + 0xc86ab5c39fa63441, + 0xfa856334878fc151, + 0x9c935e00d4b9d8d2, + 0xc3b8358109e84f07, + 0xf4a642e14c6262c9, + 0x98e7e9cccfbd7dbe, + 0xbf21e44003acdd2d, + 0xeeea5d5004981478, + 0x95527a5202df0ccb, + 0xbaa718e68396cffe, + 0xe950df20247c83fd, + 0x91d28b7416cdd27e, + ], + [ + -1077, + -1073, + -1070, + -1067, + -1063, + -1060, + -1057, + -1053, + -1050, + -1047, + -1043, + -1040, + -1037, + -1034, + -1030, + -1027, + -1024, + -1020, + -1017, + -1014, + -1010, + -1007, + -1004, + -1000, + -997, + -994, + -990, + -987, + -984, + -980, + -977, + -974, + -970, + -967, + -964, + -960, + -957, + -954, + -950, + -947, + -944, + -940, + -937, + -934, + -931, + -927, + -924, + -921, + -917, + -914, + -911, + -907, + -904, + -901, + -897, + -894, + -891, + -887, + -884, + -881, + -877, + -874, + -871, + -867, + -864, + -861, + -857, + -854, + -851, + -847, + -844, + -841, + -838, + -834, + -831, + -828, + -824, + -821, + -818, + -814, + -811, + -808, + -804, + -801, + -798, + -794, + -791, + -788, + -784, + -781, + -778, + -774, + -771, + -768, + -764, + -761, + -758, + -754, + -751, + -748, + -744, + -741, + -738, + -735, + -731, + -728, + -725, + -721, + -718, + -715, + -711, + -708, + -705, + -701, + -698, + -695, + -691, + -688, + -685, + -681, + -678, + -675, + -671, + -668, + -665, + -661, + -658, + -655, + -651, + -648, + -645, + -642, + -638, + -635, + -632, + -628, + -625, + -622, + -618, + -615, + -612, + -608, + -605, + -602, + -598, + -595, + -592, + -588, + -585, + -582, + -578, + -575, + -572, + -568, + -565, + -562, + -558, + -555, + -552, + -549, + -545, + -542, + -539, + -535, + -532, + -529, + -525, + -522, + -519, + -515, + -512, + -509, + -505, + -502, + -499, + -495, + -492, + -489, + -485, + -482, + -479, + -475, + -472, + -469, + -465, + -462, + -459, + -455, + -452, + -449, + -446, + -442, + -439, + -436, + -432, + -429, + -426, + -422, + -419, + -416, + -412, + -409, + -406, + -402, + -399, + -396, + -392, + -389, + -386, + -382, + -379, + -376, + -372, + -369, + -366, + -362, + -359, + -356, + -353, + -349, + -346, + -343, + -339, + -336, + -333, + -329, + -326, + -323, + -319, + -316, + -313, + -309, + -306, + -303, + -299, + -296, + -293, + -289, + -286, + -283, + -279, + -276, + -273, + -269, + -266, + -263, + -259, + -256, + -253, + -250, + -246, + -243, + -240, + -236, + -233, + -230, + -226, + -223, + -220, + -216, + -213, + -210, + -206, + -203, + -200, + -196, + -193, + -190, + -186, + -183, + -180, + -176, + -173, + -170, + -166, + -163, + -160, + -157, + -153, + -150, + -147, + -143, + -140, + -137, + -133, + -130, + -127, + -123, + -120, + -117, + -113, + -110, + -107, + -103, + -100, + -97, + -93, + -90, + -87, + -83, + -80, + -77, + -73, + -70, + -67, + -63, + -60, + -57, + -54, + -50, + -47, + -44, + -40, + -37, + -34, + -30, + -27, + -24, + -20, + -17, + -14, + -10, + -7, + -4, + 0, + 3, + 6, + 10, + 13, + 16, + 20, + 23, + 26, + 30, + 33, + 36, + 39, + 43, + 46, + 49, + 53, + 56, + 59, + 63, + 66, + 69, + 73, + 76, + 79, + 83, + 86, + 89, + 93, + 96, + 99, + 103, + 106, + 109, + 113, + 116, + 119, + 123, + 126, + 129, + 132, + 136, + 139, + 142, + 146, + 149, + 152, + 156, + 159, + 162, + 166, + 169, + 172, + 176, + 179, + 182, + 186, + 189, + 192, + 196, + 199, + 202, + 206, + 209, + 212, + 216, + 219, + 222, + 226, + 229, + 232, + 235, + 239, + 242, + 245, + 249, + 252, + 255, + 259, + 262, + 265, + 269, + 272, + 275, + 279, + 282, + 285, + 289, + 292, + 295, + 299, + 302, + 305, + 309, + 312, + 315, + 319, + 322, + 325, + 328, + 332, + 335, + 338, + 342, + 345, + 348, + 352, + 355, + 358, + 362, + 365, + 368, + 372, + 375, + 378, + 382, + 385, + 388, + 392, + 395, + 398, + 402, + 405, + 408, + 412, + 415, + 418, + 422, + 425, + 428, + 431, + 435, + 438, + 441, + 445, + 448, + 451, + 455, + 458, + 461, + 465, + 468, + 471, + 475, + 478, + 481, + 485, + 488, + 491, + 495, + 498, + 501, + 505, + 508, + 511, + 515, + 518, + 521, + 524, + 528, + 531, + 534, + 538, + 541, + 544, + 548, + 551, + 554, + 558, + 561, + 564, + 568, + 571, + 574, + 578, + 581, + 584, + 588, + 591, + 594, + 598, + 601, + 604, + 608, + 611, + 614, + 617, + 621, + 624, + 627, + 631, + 634, + 637, + 641, + 644, + 647, + 651, + 654, + 657, + 661, + 664, + 667, + 671, + 674, + 677, + 681, + 684, + 687, + 691, + 694, + 697, + 701, + 704, + 707, + 711, + 714, + 717, + 720, + 724, + 727, + 730, + 734, + 737, + 740, + 744, + 747, + 750, + 754, + 757, + 760, + 764, + 767, + 770, + 774, + 777, + 780, + 784, + 787, + 790, + 794, + 797, + 800, + 804, + 807, + 810, + 813, + 817, + 820, + 823, + 827, + 830, + 833, + 837, + 840, + 843, + 847, + 850, + 853, + 857, + 860, + 863, + 867, + 870, + 873, + 877, + 880, + 883, + 887, + 890, + 893, + 897, + 900, + 903, + 907, + 910, + 913, + 916, + 920, + 923, + 926, + 930, + 933, + 936, + 940, + 943, + 946, + 950, + ], +); +#[rustfmt::skip] pub const F32_SHORT_POWERS: [f32; 11] = [ 1e0, 1e1, @@ -1244,6 +1249,7 @@ pub const F32_SHORT_POWERS: [f32; 11] = [ 1e10, ]; +#[rustfmt::skip] pub const F64_SHORT_POWERS: [f64; 23] = [ 1e0, 1e1, diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs index cdf3329894..0e601d45a2 100644 --- a/src/libcore/num/diy_float.rs +++ b/src/libcore/num/diy_float.rs @@ -3,9 +3,11 @@ // This module is only for dec2flt and flt2dec, and only public because of coretests. // It is not intended to ever be stabilized. #![doc(hidden)] -#![unstable(feature = "core_private_diy_float", - reason = "internal routines only exposed for testing", - issue = "0")] +#![unstable( + feature = "core_private_diy_float", + reason = "internal routines only exposed for testing", + issue = "0" +)] /// A custom 64-bit floating point type, representing `f * 2^e`. #[derive(Copy, Clone, Debug)] @@ -74,9 +76,6 @@ impl Fp { assert!(edelta >= 0); let edelta = edelta as usize; assert_eq!(self.f << edelta >> edelta, self.f); - Fp { - f: self.f << edelta, - e, - } + Fp { f: self.f << edelta, e } } } diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 5730088c4d..ac06f95e24 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -7,9 +7,10 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +use crate::convert::FloatToInt; #[cfg(not(test))] use crate::intrinsics; - use crate::mem; use crate::num::FpCategory; @@ -26,7 +27,7 @@ pub const DIGITS: u32 = 6; /// [Machine epsilon] value for `f32`. /// -/// This is the difference between `1.0` and the next largest representable number. +/// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon #[stable(feature = "rust1", since = "1.0.0")] @@ -75,6 +76,12 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const PI: f32 = 3.14159265358979323846264338327950288_f32; + /// The full circle constant (τ) + /// + /// Equal to 2π. + #[unstable(feature = "tau_constant", issue = "66770")] + pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; + /// π/2 #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32; @@ -394,6 +401,35 @@ impl f32 { intrinsics::minnumf32(self, other) } + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// #![feature(float_approx_unchecked_to)] + /// + /// let value = 4.6_f32; + /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f32; + /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// assert_eq!(rounded, std::i8::MIN); + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[cfg(not(bootstrap))] + #[unstable(feature = "float_approx_unchecked_to", issue = "67058")] + #[inline] + pub unsafe fn approx_unchecked_to(self) -> Int where Self: FloatToInt { + FloatToInt::::approx_unchecked(self) + } + /// Raw transmutation to `u32`. /// /// This is currently identical to `transmute::(self)` on all platforms. @@ -414,6 +450,7 @@ impl f32 { #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn to_bits(self) -> u32 { + // SAFETY: `u32` is a plain old datatype so we can always transmute to it unsafe { mem::transmute(self) } } @@ -456,6 +493,7 @@ impl f32 { #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn from_bits(v: u32) -> Self { + // SAFETY: `u32` is a plain old datatype so we can always transmute from it // It turns out the safety issues with sNaN were overblown! Hooray! unsafe { mem::transmute(v) } } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 2bdeda340d..5446ce3e3b 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -7,9 +7,10 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +use crate::convert::FloatToInt; #[cfg(not(test))] use crate::intrinsics; - use crate::mem; use crate::num::FpCategory; @@ -26,7 +27,7 @@ pub const DIGITS: u32 = 15; /// [Machine epsilon] value for `f64`. /// -/// This is the difference between `1.0` and the next largest representable number. +/// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon #[stable(feature = "rust1", since = "1.0.0")] @@ -75,6 +76,12 @@ pub mod consts { #[stable(feature = "rust1", since = "1.0.0")] pub const PI: f64 = 3.14159265358979323846264338327950288_f64; + /// The full circle constant (τ) + /// + /// Equal to 2π. + #[unstable(feature = "tau_constant", issue = "66770")] + pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; + /// π/2 #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64; @@ -407,6 +414,38 @@ impl f64 { intrinsics::minnumf64(self, other) } + /// Rounds toward zero and converts to any primitive integer type, + /// assuming that the value is finite and fits in that type. + /// + /// ``` + /// #![feature(float_approx_unchecked_to)] + /// + /// let value = 4.6_f32; + /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// assert_eq!(rounded, 4); + /// + /// let value = -128.9_f32; + /// let rounded = unsafe { value.approx_unchecked_to::() }; + /// assert_eq!(rounded, std::i8::MIN); + /// ``` + /// + /// # Safety + /// + /// The value must: + /// + /// * Not be `NaN` + /// * Not be infinite + /// * Be representable in the return type `Int`, after truncating off its fractional part + #[cfg(not(bootstrap))] + #[unstable(feature = "float_approx_unchecked_to", issue = "67058")] + #[inline] + pub unsafe fn approx_unchecked_to(self) -> Int + where + Self: FloatToInt, + { + FloatToInt::::approx_unchecked(self) + } + /// Raw transmutation to `u64`. /// /// This is currently identical to `transmute::(self)` on all platforms. @@ -427,6 +466,7 @@ impl f64 { #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn to_bits(self) -> u64 { + // SAFETY: `u64` is a plain old datatype so we can always transmute to it unsafe { mem::transmute(self) } } @@ -469,6 +509,7 @@ impl f64 { #[stable(feature = "float_bits_conv", since = "1.20.0")] #[inline] pub fn from_bits(v: u64) -> Self { + // SAFETY: `u64` is a plain old datatype so we can always transmute from it // It turns out the safety issues with sNaN were overblown! Hooray! unsafe { mem::transmute(v) } } diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs index ee0f18ba29..2b74effbe2 100644 --- a/src/libcore/num/flt2dec/decoder.rs +++ b/src/libcore/num/flt2dec/decoder.rs @@ -1,8 +1,8 @@ //! Decodes a floating-point value into individual parts and error ranges. -use crate::{f32, f64}; -use crate::num::FpCategory; use crate::num::dec2flt::rawfp::RawFloat; +use crate::num::FpCategory; +use crate::{f32, f64}; /// Decoded unsigned finite value, such that: /// @@ -47,11 +47,15 @@ pub trait DecodableFloat: RawFloat + Copy { } impl DecodableFloat for f32 { - fn min_pos_norm_value() -> Self { f32::MIN_POSITIVE } + fn min_pos_norm_value() -> Self { + f32::MIN_POSITIVE + } } impl DecodableFloat for f64 { - fn min_pos_norm_value() -> Self { f64::MIN_POSITIVE } + fn min_pos_norm_value() -> Self { + f64::MIN_POSITIVE + } } /// Returns a sign (true when negative) and `FullDecoded` value @@ -67,20 +71,29 @@ pub fn decode(v: T) -> (/*negative?*/ bool, FullDecoded) { // neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp) // Float::integer_decode always preserves the exponent, // so the mantissa is scaled for subnormals. - FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1, - exp, inclusive: even }) + FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1, exp, inclusive: even }) } FpCategory::Normal => { let minnorm = ::min_pos_norm_value().integer_decode(); if mant == minnorm.0 { // neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp) // where maxmant = minnormmant * 2 - 1 - FullDecoded::Finite(Decoded { mant: mant << 2, minus: 1, plus: 2, - exp: exp - 2, inclusive: even }) + FullDecoded::Finite(Decoded { + mant: mant << 2, + minus: 1, + plus: 2, + exp: exp - 2, + inclusive: even, + }) } else { // neighbors: (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp) - FullDecoded::Finite(Decoded { mant: mant << 1, minus: 1, plus: 1, - exp: exp - 1, inclusive: even }) + FullDecoded::Finite(Decoded { + mant: mant << 1, + minus: 1, + plus: 1, + exp: exp - 1, + inclusive: even, + }) } } }; diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index 6d42a77744..63df561345 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -116,15 +116,17 @@ functions. // while this is extensively documented, this is in principle private which is // only made public for testing. do not expose us. #![doc(hidden)] -#![unstable(feature = "flt2dec", - reason = "internal routines only exposed for testing", - issue = "0")] +#![unstable( + feature = "flt2dec", + reason = "internal routines only exposed for testing", + issue = "0" +)] +pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded}; use crate::i16; -pub use self::decoder::{decode, DecodableFloat, FullDecoded, Decoded}; -pub mod estimator; pub mod decoder; +pub mod estimator; /// Digit-generation algorithms. pub mod strategy { @@ -144,17 +146,24 @@ pub const MAX_SIG_DIGITS: usize = 17; #[doc(hidden)] pub fn round_up(d: &mut [u8], n: usize) -> Option { match d[..n].iter().rposition(|&c| c != b'9') { - Some(i) => { // d[i+1..n] is all nines + Some(i) => { + // d[i+1..n] is all nines d[i] += 1; - for j in i+1..n { d[j] = b'0'; } + for j in i + 1..n { + d[j] = b'0'; + } None } - None if n > 0 => { // 999..999 rounds to 1000..000 with an increased exponent + None if n > 0 => { + // 999..999 rounds to 1000..000 with an increased exponent d[0] = b'1'; - for j in 1..n { d[j] = b'0'; } + for j in 1..n { + d[j] = b'0'; + } Some(b'0') } - None => { // an empty buffer rounds up (a bit strange but reasonable) + None => { + // an empty buffer rounds up (a bit strange but reasonable) Some(b'1') } } @@ -176,8 +185,19 @@ impl<'a> Part<'a> { pub fn len(&self) -> usize { match *self { Part::Zero(nzeroes) => nzeroes, - Part::Num(v) => if v < 1_000 { if v < 10 { 1 } else if v < 100 { 2 } else { 3 } } - else { if v < 10_000 { 4 } else { 5 } }, + Part::Num(v) => { + if v < 1_000 { + if v < 10 { + 1 + } else if v < 100 { + 2 + } else { + 3 + } + } else { + if v < 10_000 { 4 } else { 5 } + } + } Part::Copy(buf) => buf.len(), } } @@ -190,7 +210,9 @@ impl<'a> Part<'a> { if out.len() >= len { match *self { Part::Zero(nzeroes) => { - for c in &mut out[..nzeroes] { *c = b'0'; } + for c in &mut out[..nzeroes] { + *c = b'0'; + } } Part::Num(mut v) => { for c in out[..len].iter_mut().rev() { @@ -234,7 +256,9 @@ impl<'a> Formatted<'a> { /// Returns the number of written bytes, or `None` if the buffer is not enough. /// (It may still leave partially written bytes in the buffer; do not rely on that.) pub fn write(&self, out: &mut [u8]) -> Option { - if out.len() < self.sign.len() { return None; } + if out.len() < self.sign.len() { + return None; + } out[..self.sign.len()].copy_from_slice(self.sign); let mut written = self.sign.len(); @@ -254,8 +278,12 @@ impl<'a> Formatted<'a> { /// it will be ignored and full digits will be printed. It is only used to print /// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that /// it will only print given digits and nothing else. -fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize, - parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] { +fn digits_to_dec_str<'a>( + buf: &'a [u8], + exp: i16, + frac_digits: usize, + parts: &'a mut [Part<'a>], +) -> &'a [Part<'a>] { assert!(!buf.is_empty()); assert!(buf[0] > b'0'); assert!(parts.len() >= 4); @@ -322,8 +350,13 @@ fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize, /// it will be ignored and full digits will be printed. It is only used to print /// additional zeroes after rendered digits. Thus, `min_digits == 0` means that /// it will only print the given digits and nothing else. -fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: bool, - parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] { +fn digits_to_exp_str<'a>( + buf: &'a [u8], + exp: i16, + min_ndigits: usize, + upper: bool, + parts: &'a mut [Part<'a>], +) -> &'a [Part<'a>] { assert!(!buf.is_empty()); assert!(buf[0] > b'0'); assert!(parts.len() >= 6); @@ -359,11 +392,11 @@ fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: boo #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Sign { /// Prints `-` only for the negative non-zero values. - Minus, // -inf -1 0 0 1 inf nan + Minus, // -inf -1 0 0 1 inf nan /// Prints `-` only for any negative values (including the negative zero). - MinusRaw, // -inf -1 -0 0 1 inf nan + MinusRaw, // -inf -1 -0 0 1 inf nan /// Prints `-` for the negative non-zero values, or `+` otherwise. - MinusPlus, // -inf -1 +0 +0 +1 +inf nan + MinusPlus, // -inf -1 +0 +0 +1 +inf nan /// Prints `-` for any negative values (including the negative zero), or `+` otherwise. MinusPlusRaw, // -inf -1 -0 +0 +1 +inf nan } @@ -374,11 +407,35 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static match (*decoded, sign) { (FullDecoded::Nan, _) => b"", (FullDecoded::Zero, Sign::Minus) => b"", - (FullDecoded::Zero, Sign::MinusRaw) => if negative { b"-" } else { b"" }, + (FullDecoded::Zero, Sign::MinusRaw) => { + if negative { + b"-" + } else { + b"" + } + } (FullDecoded::Zero, Sign::MinusPlus) => b"+", - (FullDecoded::Zero, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" }, - (_, Sign::Minus) | (_, Sign::MinusRaw) => if negative { b"-" } else { b"" }, - (_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" }, + (FullDecoded::Zero, Sign::MinusPlusRaw) => { + if negative { + b"-" + } else { + b"+" + } + } + (_, Sign::Minus) | (_, Sign::MinusRaw) => { + if negative { + b"-" + } else { + b"" + } + } + (_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => { + if negative { + b"-" + } else { + b"+" + } + } } } @@ -400,10 +457,19 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static /// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long. /// There should be at least 4 parts available, due to the worst case like /// `[+][0.][0000][2][0000]` with `frac_digits = 10`. -pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, - sign: Sign, frac_digits: usize, _upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +pub fn to_shortest_str<'a, T, F>( + mut format_shortest: F, + v: T, + sign: Sign, + frac_digits: usize, + _upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), +{ assert!(parts.len() >= 4); assert!(buf.len() >= MAX_SIG_DIGITS); @@ -419,7 +485,8 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, Formatted { sign, parts: &parts[..1] } } FullDecoded::Zero => { - if frac_digits > 0 { // [0.][0000] + if frac_digits > 0 { + // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); Formatted { sign, parts: &parts[..2] } @@ -430,8 +497,7 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, } FullDecoded::Finite(ref decoded) => { let (len, exp) = format_shortest(decoded, buf); - Formatted { sign, - parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } + Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } } } } @@ -455,10 +521,19 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, /// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long. /// There should be at least 6 parts available, due to the worst case like /// `[+][1][.][2345][e][-][6]`. -pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, - sign: Sign, dec_bounds: (i16, i16), upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +pub fn to_shortest_exp_str<'a, T, F>( + mut format_shortest: F, + v: T, + sign: Sign, + dec_bounds: (i16, i16), + upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), +{ assert!(parts.len() >= 6); assert!(buf.len() >= MAX_SIG_DIGITS); assert!(dec_bounds.0 <= dec_bounds.1); @@ -534,10 +609,19 @@ fn estimate_max_buf_len(exp: i16) -> usize { /// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.) /// There should be at least 6 parts available, due to the worst case like /// `[+][1][.][2345][e][-][6]`. -pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, - sign: Sign, ndigits: usize, upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { +pub fn to_exact_exp_str<'a, T, F>( + mut format_exact: F, + v: T, + sign: Sign, + ndigits: usize, + upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), +{ assert!(parts.len() >= 6); assert!(ndigits > 0); @@ -553,7 +637,8 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, Formatted { sign, parts: &parts[..1] } } FullDecoded::Zero => { - if ndigits > 1 { // [0.][0000][e0] + if ndigits > 1 { + // [0.][0000][e0] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(ndigits - 1); parts[2] = Part::Copy(if upper { b"E0" } else { b"e0" }); @@ -569,8 +654,7 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, let trunc = if ndigits < maxlen { ndigits } else { maxlen }; let (len, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN); - Formatted { sign, - parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) } + Formatted { sign, parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) } } } } @@ -590,10 +674,19 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, /// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.) /// There should be at least 4 parts available, due to the worst case like /// `[+][0.][0000][2][0000]` with `frac_digits = 10`. -pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, - sign: Sign, frac_digits: usize, _upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { +pub fn to_exact_fixed_str<'a, T, F>( + mut format_exact: F, + v: T, + sign: Sign, + frac_digits: usize, + _upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>], +) -> Formatted<'a> +where + T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), +{ assert!(parts.len() >= 4); let (negative, full_decoded) = decode(v); @@ -608,7 +701,8 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, Formatted { sign, parts: &parts[..1] } } FullDecoded::Zero => { - if frac_digits > 0 { // [0.][0000] + if frac_digits > 0 { + // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); Formatted { sign, parts: &parts[..2] } @@ -631,7 +725,8 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, // `exp` was. this does not include the case that the restriction has been met // only after the final rounding-up; it's a regular case with `exp = limit + 1`. debug_assert_eq!(len, 0); - if frac_digits > 0 { // [0.][0000] + if frac_digits > 0 { + // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); Formatted { sign, parts: &parts[..2] } @@ -640,8 +735,7 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, Formatted { sign, parts: &parts[..1] } } } else { - Formatted { sign, - parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } + Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } } } } diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index 35fb4b9275..c8de000435 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -6,38 +6,54 @@ use crate::cmp::Ordering; -use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; -use crate::num::flt2dec::estimator::estimate_scaling_factor; -use crate::num::bignum::Digit32 as Digit; use crate::num::bignum::Big32x40 as Big; +use crate::num::bignum::Digit32 as Digit; +use crate::num::flt2dec::estimator::estimate_scaling_factor; +use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS}; -static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, - 1000000, 10000000, 100000000, 1000000000]; -static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000, - 2000000, 20000000, 200000000, 2000000000]; +static POW10: [Digit; 10] = + [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; +static TWOPOW10: [Digit; 10] = + [2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000]; // precalculated arrays of `Digit`s for 10^(2^n) static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2]; static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee]; static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03]; -static POW10TO128: [Digit; 14] = - [0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, - 0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x24e]; -static POW10TO256: [Digit; 27] = - [0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, - 0xcf4a6e70, 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, - 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7]; +static POW10TO128: [Digit; 14] = [ + 0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, + 0xa6337f19, 0xe91f2603, 0x24e, +]; +static POW10TO256: [Digit; 27] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, + 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, + 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7, +]; #[doc(hidden)] pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big { debug_assert!(n < 512); - if n & 7 != 0 { x.mul_small(POW10[n & 7]); } - if n & 8 != 0 { x.mul_small(POW10[8]); } - if n & 16 != 0 { x.mul_digits(&POW10TO16); } - if n & 32 != 0 { x.mul_digits(&POW10TO32); } - if n & 64 != 0 { x.mul_digits(&POW10TO64); } - if n & 128 != 0 { x.mul_digits(&POW10TO128); } - if n & 256 != 0 { x.mul_digits(&POW10TO256); } + if n & 7 != 0 { + x.mul_small(POW10[n & 7]); + } + if n & 8 != 0 { + x.mul_small(POW10[8]); + } + if n & 16 != 0 { + x.mul_digits(&POW10TO16); + } + if n & 32 != 0 { + x.mul_digits(&POW10TO32); + } + if n & 64 != 0 { + x.mul_digits(&POW10TO64); + } + if n & 128 != 0 { + x.mul_digits(&POW10TO128); + } + if n & 256 != 0 { + x.mul_digits(&POW10TO256); + } x } @@ -52,13 +68,30 @@ fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big { } // only usable when `x < 16 * scale`; `scaleN` should be `scale.mul_small(N)` -fn div_rem_upto_16<'a>(x: &'a mut Big, scale: &Big, - scale2: &Big, scale4: &Big, scale8: &Big) -> (u8, &'a mut Big) { +fn div_rem_upto_16<'a>( + x: &'a mut Big, + scale: &Big, + scale2: &Big, + scale4: &Big, + scale8: &Big, +) -> (u8, &'a mut Big) { let mut d = 0; - if *x >= *scale8 { x.sub(scale8); d += 8; } - if *x >= *scale4 { x.sub(scale4); d += 4; } - if *x >= *scale2 { x.sub(scale2); d += 2; } - if *x >= *scale { x.sub(scale); d += 1; } + if *x >= *scale8 { + x.sub(scale8); + d += 8; + } + if *x >= *scale4 { + x.sub(scale4); + d += 4; + } + if *x >= *scale2 { + x.sub(scale2); + d += 2; + } + if *x >= *scale { + x.sub(scale); + d += 1; + } debug_assert!(*x < *scale); (d, x) } @@ -85,7 +118,7 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp assert!(buf.len() >= MAX_SIG_DIGITS); // `a.cmp(&b) < rounding` is `if d.inclusive {a <= b} else {a < b}` - let rounding = if d.inclusive {Ordering::Greater} else {Ordering::Equal}; + let rounding = if d.inclusive { Ordering::Greater } else { Ordering::Equal }; // estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= 10^(k_0+1)`. // the tight bound `k` satisfying `10^(k-1) < high <= 10^k` is calculated later. @@ -132,9 +165,12 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp } // cache `(2, 4, 8) * scale` for digit generation. - let mut scale2 = scale.clone(); scale2.mul_pow2(1); - let mut scale4 = scale.clone(); scale4.mul_pow2(2); - let mut scale8 = scale.clone(); scale8.mul_pow2(3); + let mut scale2 = scale.clone(); + scale2.mul_pow2(1); + let mut scale4 = scale.clone(); + scale4.mul_pow2(2); + let mut scale8 = scale.clone(); + scale8.mul_pow2(3); let mut down; let mut up; @@ -186,7 +222,9 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp // - keep generating otherwise. down = mant.cmp(&minus) < rounding; up = scale.cmp(mant.clone().add(&plus)) < rounding; - if down || up { break; } // we have the shortest representation, proceed to the rounding + if down || up { + break; + } // we have the shortest representation, proceed to the rounding // restore the invariants. // this makes the algorithm always terminating: `minus` and `plus` always increases, @@ -269,22 +307,40 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi if len > 0 { // cache `(2, 4, 8) * scale` for digit generation. // (this can be expensive, so do not calculate them when the buffer is empty.) - let mut scale2 = scale.clone(); scale2.mul_pow2(1); - let mut scale4 = scale.clone(); scale4.mul_pow2(2); - let mut scale8 = scale.clone(); scale8.mul_pow2(3); + let mut scale2 = scale.clone(); + scale2.mul_pow2(1); + let mut scale4 = scale.clone(); + scale4.mul_pow2(2); + let mut scale8 = scale.clone(); + scale8.mul_pow2(3); for i in 0..len { - if mant.is_zero() { // following digits are all zeroes, we stop here + if mant.is_zero() { + // following digits are all zeroes, we stop here // do *not* try to perform rounding! rather, fill remaining digits. - for c in &mut buf[i..len] { *c = b'0'; } + for c in &mut buf[i..len] { + *c = b'0'; + } return (len, k); } let mut d = 0; - if mant >= scale8 { mant.sub(&scale8); d += 8; } - if mant >= scale4 { mant.sub(&scale4); d += 4; } - if mant >= scale2 { mant.sub(&scale2); d += 2; } - if mant >= scale { mant.sub(&scale); d += 1; } + if mant >= scale8 { + mant.sub(&scale8); + d += 8; + } + if mant >= scale4 { + mant.sub(&scale4); + d += 4; + } + if mant >= scale2 { + mant.sub(&scale2); + d += 2; + } + if mant >= scale { + mant.sub(&scale); + d += 1; + } debug_assert!(mant < scale); debug_assert!(d < 10); buf[i] = b'0' + d; @@ -296,8 +352,9 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi // if the following digits are exactly 5000..., check the prior digit and try to // round to even (i.e., avoid rounding up when the prior digit is even). let order = mant.cmp(scale.mul_small(5)); - if order == Ordering::Greater || (order == Ordering::Equal && - (len == 0 || buf[len-1] & 1 == 1)) { + if order == Ordering::Greater + || (order == Ordering::Equal && (len == 0 || buf[len - 1] & 1 == 1)) + { // if rounding up changes the length, the exponent should also change. // but we've been requested a fixed number of digits, so do not alter the buffer... if let Some(c) = round_up(buf, len) { diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index 61b50ec8ca..1e2db212dd 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -6,12 +6,13 @@ //! accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243. use crate::num::diy_float::Fp; -use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; - +use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS}; // see the comments in `format_shortest_opt` for the rationale. -#[doc(hidden)] pub const ALPHA: i16 = -60; -#[doc(hidden)] pub const GAMMA: i16 = -32; +#[doc(hidden)] +pub const ALPHA: i16 = -60; +#[doc(hidden)] +pub const GAMMA: i16 = -32; /* # the following Python code generates this table: @@ -24,92 +25,95 @@ for i in xrange(-308, 333, 8): */ #[doc(hidden)] -pub static CACHED_POW10: [(u64, i16, i16); 81] = [ // (f, e, k) +pub static CACHED_POW10: [(u64, i16, i16); 81] = [ + // (f, e, k) (0xe61acf033d1a45df, -1087, -308), (0xab70fe17c79ac6ca, -1060, -300), (0xff77b1fcbebcdc4f, -1034, -292), (0xbe5691ef416bd60c, -1007, -284), - (0x8dd01fad907ffc3c, -980, -276), - (0xd3515c2831559a83, -954, -268), - (0x9d71ac8fada6c9b5, -927, -260), - (0xea9c227723ee8bcb, -901, -252), - (0xaecc49914078536d, -874, -244), - (0x823c12795db6ce57, -847, -236), - (0xc21094364dfb5637, -821, -228), - (0x9096ea6f3848984f, -794, -220), - (0xd77485cb25823ac7, -768, -212), - (0xa086cfcd97bf97f4, -741, -204), - (0xef340a98172aace5, -715, -196), - (0xb23867fb2a35b28e, -688, -188), - (0x84c8d4dfd2c63f3b, -661, -180), - (0xc5dd44271ad3cdba, -635, -172), - (0x936b9fcebb25c996, -608, -164), - (0xdbac6c247d62a584, -582, -156), - (0xa3ab66580d5fdaf6, -555, -148), - (0xf3e2f893dec3f126, -529, -140), - (0xb5b5ada8aaff80b8, -502, -132), - (0x87625f056c7c4a8b, -475, -124), - (0xc9bcff6034c13053, -449, -116), - (0x964e858c91ba2655, -422, -108), - (0xdff9772470297ebd, -396, -100), - (0xa6dfbd9fb8e5b88f, -369, -92), - (0xf8a95fcf88747d94, -343, -84), - (0xb94470938fa89bcf, -316, -76), - (0x8a08f0f8bf0f156b, -289, -68), - (0xcdb02555653131b6, -263, -60), - (0x993fe2c6d07b7fac, -236, -52), - (0xe45c10c42a2b3b06, -210, -44), - (0xaa242499697392d3, -183, -36), - (0xfd87b5f28300ca0e, -157, -28), - (0xbce5086492111aeb, -130, -20), - (0x8cbccc096f5088cc, -103, -12), - (0xd1b71758e219652c, -77, -4), - (0x9c40000000000000, -50, 4), - (0xe8d4a51000000000, -24, 12), - (0xad78ebc5ac620000, 3, 20), - (0x813f3978f8940984, 30, 28), - (0xc097ce7bc90715b3, 56, 36), - (0x8f7e32ce7bea5c70, 83, 44), - (0xd5d238a4abe98068, 109, 52), - (0x9f4f2726179a2245, 136, 60), - (0xed63a231d4c4fb27, 162, 68), - (0xb0de65388cc8ada8, 189, 76), - (0x83c7088e1aab65db, 216, 84), - (0xc45d1df942711d9a, 242, 92), - (0x924d692ca61be758, 269, 100), - (0xda01ee641a708dea, 295, 108), - (0xa26da3999aef774a, 322, 116), - (0xf209787bb47d6b85, 348, 124), - (0xb454e4a179dd1877, 375, 132), - (0x865b86925b9bc5c2, 402, 140), - (0xc83553c5c8965d3d, 428, 148), - (0x952ab45cfa97a0b3, 455, 156), - (0xde469fbd99a05fe3, 481, 164), - (0xa59bc234db398c25, 508, 172), - (0xf6c69a72a3989f5c, 534, 180), - (0xb7dcbf5354e9bece, 561, 188), - (0x88fcf317f22241e2, 588, 196), - (0xcc20ce9bd35c78a5, 614, 204), - (0x98165af37b2153df, 641, 212), - (0xe2a0b5dc971f303a, 667, 220), - (0xa8d9d1535ce3b396, 694, 228), - (0xfb9b7cd9a4a7443c, 720, 236), - (0xbb764c4ca7a44410, 747, 244), - (0x8bab8eefb6409c1a, 774, 252), - (0xd01fef10a657842c, 800, 260), - (0x9b10a4e5e9913129, 827, 268), - (0xe7109bfba19c0c9d, 853, 276), - (0xac2820d9623bf429, 880, 284), - (0x80444b5e7aa7cf85, 907, 292), - (0xbf21e44003acdd2d, 933, 300), - (0x8e679c2f5e44ff8f, 960, 308), - (0xd433179d9c8cb841, 986, 316), - (0x9e19db92b4e31ba9, 1013, 324), - (0xeb96bf6ebadf77d9, 1039, 332), + (0x8dd01fad907ffc3c, -980, -276), + (0xd3515c2831559a83, -954, -268), + (0x9d71ac8fada6c9b5, -927, -260), + (0xea9c227723ee8bcb, -901, -252), + (0xaecc49914078536d, -874, -244), + (0x823c12795db6ce57, -847, -236), + (0xc21094364dfb5637, -821, -228), + (0x9096ea6f3848984f, -794, -220), + (0xd77485cb25823ac7, -768, -212), + (0xa086cfcd97bf97f4, -741, -204), + (0xef340a98172aace5, -715, -196), + (0xb23867fb2a35b28e, -688, -188), + (0x84c8d4dfd2c63f3b, -661, -180), + (0xc5dd44271ad3cdba, -635, -172), + (0x936b9fcebb25c996, -608, -164), + (0xdbac6c247d62a584, -582, -156), + (0xa3ab66580d5fdaf6, -555, -148), + (0xf3e2f893dec3f126, -529, -140), + (0xb5b5ada8aaff80b8, -502, -132), + (0x87625f056c7c4a8b, -475, -124), + (0xc9bcff6034c13053, -449, -116), + (0x964e858c91ba2655, -422, -108), + (0xdff9772470297ebd, -396, -100), + (0xa6dfbd9fb8e5b88f, -369, -92), + (0xf8a95fcf88747d94, -343, -84), + (0xb94470938fa89bcf, -316, -76), + (0x8a08f0f8bf0f156b, -289, -68), + (0xcdb02555653131b6, -263, -60), + (0x993fe2c6d07b7fac, -236, -52), + (0xe45c10c42a2b3b06, -210, -44), + (0xaa242499697392d3, -183, -36), + (0xfd87b5f28300ca0e, -157, -28), + (0xbce5086492111aeb, -130, -20), + (0x8cbccc096f5088cc, -103, -12), + (0xd1b71758e219652c, -77, -4), + (0x9c40000000000000, -50, 4), + (0xe8d4a51000000000, -24, 12), + (0xad78ebc5ac620000, 3, 20), + (0x813f3978f8940984, 30, 28), + (0xc097ce7bc90715b3, 56, 36), + (0x8f7e32ce7bea5c70, 83, 44), + (0xd5d238a4abe98068, 109, 52), + (0x9f4f2726179a2245, 136, 60), + (0xed63a231d4c4fb27, 162, 68), + (0xb0de65388cc8ada8, 189, 76), + (0x83c7088e1aab65db, 216, 84), + (0xc45d1df942711d9a, 242, 92), + (0x924d692ca61be758, 269, 100), + (0xda01ee641a708dea, 295, 108), + (0xa26da3999aef774a, 322, 116), + (0xf209787bb47d6b85, 348, 124), + (0xb454e4a179dd1877, 375, 132), + (0x865b86925b9bc5c2, 402, 140), + (0xc83553c5c8965d3d, 428, 148), + (0x952ab45cfa97a0b3, 455, 156), + (0xde469fbd99a05fe3, 481, 164), + (0xa59bc234db398c25, 508, 172), + (0xf6c69a72a3989f5c, 534, 180), + (0xb7dcbf5354e9bece, 561, 188), + (0x88fcf317f22241e2, 588, 196), + (0xcc20ce9bd35c78a5, 614, 204), + (0x98165af37b2153df, 641, 212), + (0xe2a0b5dc971f303a, 667, 220), + (0xa8d9d1535ce3b396, 694, 228), + (0xfb9b7cd9a4a7443c, 720, 236), + (0xbb764c4ca7a44410, 747, 244), + (0x8bab8eefb6409c1a, 774, 252), + (0xd01fef10a657842c, 800, 260), + (0x9b10a4e5e9913129, 827, 268), + (0xe7109bfba19c0c9d, 853, 276), + (0xac2820d9623bf429, 880, 284), + (0x80444b5e7aa7cf85, 907, 292), + (0xbf21e44003acdd2d, 933, 300), + (0x8e679c2f5e44ff8f, 960, 308), + (0xd433179d9c8cb841, 986, 316), + (0x9e19db92b4e31ba9, 1013, 324), + (0xeb96bf6ebadf77d9, 1039, 332), ]; -#[doc(hidden)] pub const CACHED_POW10_FIRST_E: i16 = -1087; -#[doc(hidden)] pub const CACHED_POW10_LAST_E: i16 = 1039; +#[doc(hidden)] +pub const CACHED_POW10_FIRST_E: i16 = -1087; +#[doc(hidden)] +pub const CACHED_POW10_LAST_E: i16 = 1039; #[doc(hidden)] pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) { @@ -128,30 +132,39 @@ pub fn max_pow10_no_more_than(x: u32) -> (u8, u32) { debug_assert!(x > 0); const X9: u32 = 10_0000_0000; - const X8: u32 = 1_0000_0000; - const X7: u32 = 1000_0000; - const X6: u32 = 100_0000; - const X5: u32 = 10_0000; - const X4: u32 = 1_0000; - const X3: u32 = 1000; - const X2: u32 = 100; - const X1: u32 = 10; + const X8: u32 = 1_0000_0000; + const X7: u32 = 1000_0000; + const X6: u32 = 100_0000; + const X5: u32 = 10_0000; + const X4: u32 = 1_0000; + const X3: u32 = 1000; + const X2: u32 = 100; + const X1: u32 = 10; if x < X4 { - if x < X2 { if x < X1 {(0, 1)} else {(1, X1)} } - else { if x < X3 {(2, X2)} else {(3, X3)} } + if x < X2 { + if x < X1 { (0, 1) } else { (1, X1) } + } else { + if x < X3 { (2, X2) } else { (3, X3) } + } } else { - if x < X6 { if x < X5 {(4, X4)} else {(5, X5)} } - else if x < X8 { if x < X7 {(6, X6)} else {(7, X7)} } - else { if x < X9 {(8, X8)} else {(9, X9)} } + if x < X6 { + if x < X5 { (4, X4) } else { (5, X5) } + } else if x < X8 { + if x < X7 { (6, X6) } else { (7, X7) } + } else { + if x < X9 { (8, X8) } else { (9, X9) } + } } } /// The shortest mode implementation for Grisu. /// /// It returns `None` when it would return an inexact representation otherwise. -pub fn format_shortest_opt(d: &Decoded, - buf: &mut [u8]) -> Option<(/*#digits*/ usize, /*exp*/ i16)> { +pub fn format_shortest_opt( + d: &Decoded, + buf: &mut [u8], +) -> Option<(/*#digits*/ usize, /*exp*/ i16)> { assert!(d.mant > 0); assert!(d.minus > 0); assert!(d.plus > 0); @@ -208,8 +221,8 @@ pub fn format_shortest_opt(d: &Decoded, // we start with the correct repr within the unsafe region, and try to find the closest repr // to `v` which is also within the safe region. if we can't, we give up. let plus1 = plus.f + 1; -// let plus0 = plus.f - 1; // only for explanation -// let minus0 = minus.f + 1; // only for explanation + // let plus0 = plus.f - 1; // only for explanation + // let minus0 = minus.f + 1; // only for explanation let minus1 = minus.f - 1; let e = -plus.e as usize; // shared exponent @@ -235,14 +248,15 @@ pub fn format_shortest_opt(d: &Decoded, // (e.g., `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.) // the algorithm relies on the later verification phase to exclude `y`. let delta1 = plus1 - minus1; -// let delta1int = (delta1 >> e) as usize; // only for explanation + // let delta1int = (delta1 >> e) as usize; // only for explanation let delta1frac = delta1 & ((1 << e) - 1); // render integral parts, while checking for the accuracy at each step. let mut kappa = max_kappa as i16; let mut ten_kappa = max_ten_kappa; // 10^kappa let mut remainder = plus1int; // digits yet to be rendered - loop { // we always have at least one digit to render, as `plus1 >= 10^kappa` + loop { + // we always have at least one digit to render, as `plus1 >= 10^kappa` // invariants: // - `delta1int <= remainder < 10^(kappa+1)` // - `plus1int = d[0..n-1] * 10^(kappa+1) + remainder` @@ -281,7 +295,8 @@ pub fn format_shortest_opt(d: &Decoded, let mut remainder = plus1frac; let mut threshold = delta1frac; let mut ulp = 1; - loop { // the next digit should be significant as we've tested that before breaking out + loop { + // the next digit should be significant as we've tested that before breaking out // invariants, where `m = max_kappa + 1` (# of digits in the integral part): // - `remainder < 2^e` // - `plus1frac * 10^(n-m) = d[m..n-1] * 2^e + remainder` @@ -300,8 +315,15 @@ pub fn format_shortest_opt(d: &Decoded, if r < threshold { let ten_kappa = 1 << e; // implicit divisor - return round_and_weed(&mut buf[..i], exp, r, threshold, - (plus1 - v.f) * ulp, ten_kappa, ulp); + return round_and_weed( + &mut buf[..i], + exp, + r, + threshold, + (plus1 - v.f) * ulp, + ten_kappa, + ulp, + ); } // restore invariants @@ -325,8 +347,15 @@ pub fn format_shortest_opt(d: &Decoded, // - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior invariants) // - `ten_kappa = 10^kappa * k` // - `ulp = 2^-e * k` - fn round_and_weed(buf: &mut [u8], exp: i16, remainder: u64, threshold: u64, plus1v: u64, - ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> { + fn round_and_weed( + buf: &mut [u8], + exp: i16, + remainder: u64, + threshold: u64, + plus1v: u64, + ten_kappa: u64, + ulp: u64, + ) -> Option<(usize, i16)> { assert!(!buf.is_empty()); // produce two approximations to `v` (actually `plus1 - v`) within 1.5 ulps. @@ -381,10 +410,11 @@ pub fn format_shortest_opt(d: &Decoded, // // consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the following is // equal to its inverse, `!TC1 && !TC2 && (!TC3a || !TC3b)`. - while plus1w < plus1v_up && - threshold - plus1w >= ten_kappa && - (plus1w + ten_kappa < plus1v_up || - plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up) { + while plus1w < plus1v_up + && threshold - plus1w >= ten_kappa + && (plus1w + ten_kappa < plus1v_up + || plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up) + { *last -= 1; debug_assert!(*last > b'0'); // the shortest repr cannot end with `0` plus1w += ten_kappa; @@ -395,10 +425,11 @@ pub fn format_shortest_opt(d: &Decoded, // // this is simply same to the terminating conditions for `v + 1 ulp`, with all `plus1v_up` // replaced by `plus1v_down` instead. overflow analysis equally holds. - if plus1w < plus1v_down && - threshold - plus1w >= ten_kappa && - (plus1w + ten_kappa < plus1v_down || - plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down) { + if plus1w < plus1v_down + && threshold - plus1w >= ten_kappa + && (plus1w + ten_kappa < plus1v_down + || plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down) + { return None; } @@ -428,8 +459,11 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp /// The exact and fixed mode implementation for Grisu. /// /// It returns `None` when it would return an inexact representation otherwise. -pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) - -> Option<(/*#digits*/ usize, /*exp*/ i16)> { +pub fn format_exact_opt( + d: &Decoded, + buf: &mut [u8], + limit: i16, +) -> Option<(/*#digits*/ usize, /*exp*/ i16)> { assert!(d.mant > 0); assert!(d.mant < (1 << 61)); // we need at least three bits of additional precision assert!(!buf.is_empty()); @@ -489,7 +523,8 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) let mut kappa = max_kappa as i16; let mut ten_kappa = max_ten_kappa; // 10^kappa let mut remainder = vint; // digits yet to be rendered - loop { // we always have at least one digit to render + loop { + // we always have at least one digit to render // invariants: // - `remainder < 10^(kappa+1)` // - `vint = d[0..n-1] * 10^(kappa+1) + remainder` @@ -575,8 +610,15 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // - `remainder = (v % 10^kappa) * k` // - `ten_kappa = 10^kappa * k` // - `ulp = 2^-e * k` - fn possibly_round(buf: &mut [u8], mut len: usize, mut exp: i16, limit: i16, - remainder: u64, ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> { + fn possibly_round( + buf: &mut [u8], + mut len: usize, + mut exp: i16, + limit: i16, + remainder: u64, + ten_kappa: u64, + ulp: u64, + ) -> Option<(usize, i16)> { debug_assert!(remainder < ten_kappa); // 10^kappa @@ -593,7 +635,9 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // // error is too large that there are at least three possible representations // between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is correct. - if ulp >= ten_kappa { return None; } + if ulp >= ten_kappa { + return None; + } // 10^kappa // :<------->: @@ -607,7 +651,9 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // in fact, 1/2 ulp is enough to introduce two possible representations. // (remember that we need a unique representation for both `v - 1 ulp` and `v + 1 ulp`.) // this won't overflow, as `ulp < ten_kappa` from the first check. - if ten_kappa - ulp <= ulp { return None; } + if ten_kappa - ulp <= ulp { + return None; + } // remainder // :<->| : diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index b4ade70414..d091a8d86e 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4,7 +4,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::convert::{TryFrom, Infallible}; +use crate::convert::Infallible; use crate::fmt; use crate::intrinsics; use crate::mem; @@ -61,9 +61,13 @@ assert_eq!(size_of::>(), size_of::<", s /// /// The value must not be zero. #[$stability] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "nonzero", since = "1.34.0"), + )] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { - $Ty(n) + Self(n) } /// Creates a non-zero if the given value is not zero. @@ -71,7 +75,8 @@ assert_eq!(size_of::>(), size_of::<", s #[inline] pub fn new(n: $Int) -> Option { if n != 0 { - Some(unsafe { $Ty(n) }) + // SAFETY: we just checked that there's no `0` + Some(unsafe { Self(n) }) } else { None } @@ -80,6 +85,10 @@ assert_eq!(size_of::>(), size_of::<", s /// Returns the value as a primitive type. #[$stability] #[inline] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "nonzero", since = "1.34.0"), + )] pub const fn get(self) -> $Int { self.0 } @@ -131,11 +140,11 @@ macro_rules! from_str_radix_nzint_impl { } from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize - NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } +NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } /// Provides intentionally-wrapped arithmetic on `T`. /// -/// Operations like `+` on `u32` values is intended to never overflow, +/// Operations like `+` on `u32` values are intended to never overflow, /// and in some debug configurations overflow is detected and results /// in a panic. While most arithmetic falls into this category, some /// code explicitly expects and relies upon modular arithmetic (e.g., @@ -162,8 +171,7 @@ from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU #[stable(feature = "rust1", since = "1.0.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] #[repr(transparent)] -pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] - pub T); +pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Wrapping { @@ -208,33 +216,35 @@ impl fmt::UpperHex for Wrapping { } // All these modules are technically private and only exposed for coretests: -pub mod flt2dec; -pub mod dec2flt; pub mod bignum; +pub mod dec2flt; pub mod diy_float; +pub mod flt2dec; mod wrapping; macro_rules! usize_isize_to_xe_bytes_doc { - () => {" + () => { + " **Note**: This function returns an array of length 2, 4 or 8 bytes depending on the target pointer size. -"} +" + }; } - macro_rules! usize_isize_from_xe_bytes_doc { - () => {" + () => { + " **Note**: This function takes an array of length 2, 4 or 8 bytes depending on the target pointer size. -"} +" + }; } -// `Int` + `SignedInt` implemented for signed integers macro_rules! int_impl { ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $Min:expr, $Max:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, @@ -254,6 +264,10 @@ $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] #[rustc_promotable] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_min_value", since = "1.32.0"), + )] pub const fn min_value() -> Self { !0 ^ ((!0 as $UnsignedT) >> 1) as Self } @@ -273,6 +287,10 @@ $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] #[rustc_promotable] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_max_value", since = "1.32.0"), + )] pub const fn max_value() -> Self { !Self::min_value() } @@ -322,6 +340,10 @@ $EndFeature, " ``` "), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } } @@ -337,6 +359,10 @@ Basic usage: ", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 1);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn count_zeros(self) -> u32 { (!self).count_ones() @@ -357,6 +383,10 @@ assert_eq!(n.leading_zeros(), 0);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn leading_zeros(self) -> u32 { (self as $UnsignedT).leading_zeros() @@ -377,6 +407,10 @@ assert_eq!(n.trailing_zeros(), 2);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn trailing_zeros(self) -> u32 { (self as $UnsignedT).trailing_zeros() @@ -400,6 +434,10 @@ let m = ", $rot_result, "; assert_eq!(n.rotate_left(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -426,6 +464,10 @@ let m = ", $rot_op, "; assert_eq!(n.rotate_right(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -449,6 +491,10 @@ let m = n.swap_bytes(); assert_eq!(m, ", $swapped, "); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn swap_bytes(self) -> Self { (self as $UnsignedT).swap_bytes() as Self @@ -469,6 +515,10 @@ let m = n.reverse_bits(); assert_eq!(m, ", $reversed, "); ```"), #[stable(feature = "reverse_bits", since = "1.37.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] #[must_use] pub const fn reverse_bits(self) -> Self { @@ -496,6 +546,10 @@ if cfg!(target_endian = \"big\") { $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_conversions", since = "1.32.0"), + )] #[inline] pub const fn from_be(x: Self) -> Self { #[cfg(target_endian = "big")] @@ -529,6 +583,10 @@ if cfg!(target_endian = \"little\") { $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_conversions", since = "1.32.0"), + )] #[inline] pub const fn from_le(x: Self) -> Self { #[cfg(target_endian = "little")] @@ -562,6 +620,10 @@ if cfg!(target_endian = \"big\") { $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_conversions", since = "1.32.0"), + )] #[inline] pub const fn to_be(self) -> Self { // or not to be? #[cfg(target_endian = "big")] @@ -595,6 +657,10 @@ if cfg!(target_endian = \"little\") { $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_conversions", since = "1.32.0"), + )] #[inline] pub const fn to_le(self) -> Self { #[cfg(target_endian = "little")] @@ -703,6 +769,7 @@ $EndFeature, " if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { + // SAFETY: div by zero and by INT_MIN have been checked above Some(unsafe { intrinsics::unchecked_div(self, rhs) }) } } @@ -759,6 +826,7 @@ $EndFeature, " if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { + // SAFETY: div by zero and by INT_MIN have been checked above Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) } } @@ -945,7 +1013,11 @@ $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_saturating_int_methods")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_saturating_int_methods"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -971,7 +1043,11 @@ assert_eq!(", stringify!($SelfT), "::max_value().saturating_sub(-1), ", stringif $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_saturating_int_methods")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_saturating_int_methods"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1111,6 +1187,10 @@ assert_eq!(", stringify!($SelfT), "::max_value().wrapping_add(2), ", stringify!( $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1134,6 +1214,10 @@ stringify!($SelfT), "::max_value());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1156,6 +1240,10 @@ assert_eq!(11i8.wrapping_mul(12), -124);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1300,6 +1388,10 @@ assert_eq!(", stringify!($SelfT), "::min_value().wrapping_neg(), ", stringify!($ $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn wrapping_neg(self) -> Self { self.overflowing_neg().0 @@ -1325,10 +1417,16 @@ assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] pub const fn wrapping_shl(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds unsafe { intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -1354,10 +1452,16 @@ assert_eq!((-128i16).wrapping_shr(64), -128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] pub const fn wrapping_shr(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds unsafe { intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -1385,6 +1489,10 @@ assert_eq!((-128i8).wrapping_abs() as u8, 128);", $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn wrapping_abs(self) -> Self { // sign is -1 (all ones) for negative numbers, 0 otherwise. @@ -1459,6 +1567,10 @@ assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($Sel "::MIN, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1486,6 +1598,10 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($Sel "::MAX, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1511,6 +1627,10 @@ assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1678,6 +1798,10 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($Self ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] pub const fn overflowing_neg(self) -> (Self, bool) { ((!self).wrapping_add(1), self == Self::min_value()) } @@ -1700,6 +1824,10 @@ assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1725,6 +1853,10 @@ assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1753,6 +1885,10 @@ assert_eq!((", stringify!($SelfT), "::min_value()).overflowing_abs(), (", string $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn overflowing_abs(self) -> (Self, bool) { (self.wrapping_abs(), self == Self::min_value()) @@ -1957,6 +2093,10 @@ assert_eq!((-10", stringify!($SelfT), ").abs(), 10);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] #[rustc_inherit_overflow_checks] pub const fn abs(self) -> Self { @@ -1999,7 +2139,11 @@ assert_eq!((-10", stringify!($SelfT), ").signum(), -1);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_int_sign")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_sign"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_sign", issue = "53718"), + )] #[inline] pub const fn signum(self) -> Self { (self > 0) as Self - (self < 0) as Self @@ -2020,6 +2164,10 @@ assert!(!(-10", stringify!($SelfT), ").is_positive());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn is_positive(self) -> bool { self > 0 } } @@ -2038,6 +2186,10 @@ assert!(!10", stringify!($SelfT), ".is_negative());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_int_methods", since = "1.32.0"), + )] #[inline] pub const fn is_negative(self) -> bool { self < 0 } } @@ -2055,7 +2207,11 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -2075,7 +2231,11 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -2110,9 +2270,15 @@ assert_eq!( ); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes unsafe { mem::transmute(self) } } } @@ -2142,7 +2308,11 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -2175,7 +2345,11 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -2218,9 +2392,14 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + // SAFETY: integers are plain old datatypes so we can always transmute to them unsafe { mem::transmute(bytes) } } } @@ -2230,70 +2409,69 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[lang = "i8"] impl i8 { int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", - "[0x12]", "[0x12]", "", "" } + "[0x12]", "[0x12]", "", "" } } #[lang = "i16"] impl i16 { int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", - "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } + "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "i32"] impl i32 { int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", - "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]", "", "" } + "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "i64"] impl i64 { int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12, - "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", - "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } + "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", + "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } } #[lang = "i128"] impl i128 { int_impl! { i128, i128, u128, 128, -170141183460469231731687303715884105728, - 170141183460469231731687303715884105727, "", "", 16, - "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", - "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", - "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ - 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" } + 170141183460469231731687303715884105727, "", "", 16, + "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", + "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", + "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" } } #[cfg(target_pointer_width = "16")] #[lang = "isize"] impl isize { int_impl! { isize, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", - "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "32")] #[lang = "isize"] impl isize { int_impl! { isize, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301", - "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "64")] #[lang = "isize"] impl isize { int_impl! { isize, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", - 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", - "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", + "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } -// `Int` + `UnsignedInt` implemented for unsigned integers macro_rules! uint_impl { ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, @@ -2312,6 +2490,10 @@ Basic usage: #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[inline(always)] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_min_value", since = "1.32.0"), + )] pub const fn min_value() -> Self { 0 } } @@ -2329,6 +2511,10 @@ stringify!($MaxV), ");", $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[inline(always)] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_max_value", since = "1.32.0"), + )] pub const fn max_value() -> Self { !0 } } @@ -2375,6 +2561,10 @@ Basic usage: assert_eq!(n.count_ones(), 3);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn count_ones(self) -> u32 { intrinsics::ctpop(self as $ActualT) as u32 @@ -2392,6 +2582,10 @@ Basic usage: ", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 0);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn count_zeros(self) -> u32 { (!self).count_ones() @@ -2411,6 +2605,10 @@ Basic usage: assert_eq!(n.leading_zeros(), 2);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn leading_zeros(self) -> u32 { intrinsics::ctlz(self as $ActualT) as u32 @@ -2431,6 +2629,10 @@ Basic usage: assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn trailing_zeros(self) -> u32 { intrinsics::cttz(self) as u32 @@ -2454,6 +2656,10 @@ let m = ", $rot_result, "; assert_eq!(n.rotate_left(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2480,6 +2686,10 @@ let m = ", $rot_op, "; assert_eq!(n.rotate_right(", $rot, "), m); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2503,6 +2713,10 @@ let m = n.swap_bytes(); assert_eq!(m, ", $swapped, "); ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn swap_bytes(self) -> Self { intrinsics::bswap(self as $ActualT) as Self @@ -2523,6 +2737,10 @@ let m = n.reverse_bits(); assert_eq!(m, ", $reversed, "); ```"), #[stable(feature = "reverse_bits", since = "1.37.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] #[must_use] pub const fn reverse_bits(self) -> Self { @@ -2550,6 +2768,10 @@ if cfg!(target_endian = \"big\") { }", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn from_be(x: Self) -> Self { #[cfg(target_endian = "big")] @@ -2583,6 +2805,10 @@ if cfg!(target_endian = \"little\") { }", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn from_le(x: Self) -> Self { #[cfg(target_endian = "little")] @@ -2616,6 +2842,10 @@ if cfg!(target_endian = \"big\") { }", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn to_be(self) -> Self { // or not to be? #[cfg(target_endian = "big")] @@ -2649,6 +2879,10 @@ if cfg!(target_endian = \"little\") { }", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_math", since = "1.32.0"), + )] #[inline] pub const fn to_le(self) -> Self { #[cfg(target_endian = "little")] @@ -2748,6 +2982,8 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " pub fn checked_div(self, rhs: Self) -> Option { match rhs { 0 => None, + // SAFETY: div by zero has been checked above and unsigned types have no other + // failure modes for division rhs => Some(unsafe { intrinsics::unchecked_div(self, rhs) }), } } @@ -2799,6 +3035,8 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " if rhs == 0 { None } else { + // SAFETY: div by zero has been checked above and unsigned types have no other + // failure modes for division Some(unsafe { intrinsics::unchecked_rem(self, rhs) }) } } @@ -2950,7 +3188,11 @@ assert_eq!(200u8.saturating_add(127), 255);", $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_const_unstable(feature = "const_saturating_int_methods")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_saturating_int_methods"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718"), + )] #[inline] pub const fn saturating_add(self, rhs: Self) -> Self { intrinsics::saturating_add(self, rhs) @@ -2972,7 +3214,11 @@ assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);", $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_const_unstable(feature = "const_saturating_int_methods")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_saturating_int_methods"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_saturating_int_methods", issue = "53718"), + )] #[inline] pub const fn saturating_sub(self, rhs: Self) -> Self { intrinsics::saturating_sub(self, rhs) @@ -3044,6 +3290,10 @@ assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::ma $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3066,6 +3316,10 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::ma $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3089,6 +3343,10 @@ $EndFeature, " /// assert_eq!(25u8.wrapping_mul(12), 44); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3218,6 +3476,10 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); /// assert_eq!((-128i8).wrapping_neg(), -128); /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[inline] pub const fn wrapping_neg(self) -> Self { self.overflowing_neg().0 @@ -3244,10 +3506,16 @@ Basic usage: assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] pub const fn wrapping_shl(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds unsafe { intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -3275,10 +3543,16 @@ Basic usage: assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] pub const fn wrapping_shr(self, rhs: u32) -> Self { + // SAFETY: the masking by the bitsize of the type ensures that we do not shift + // out of bounds unsafe { intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT) } @@ -3342,6 +3616,10 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3370,6 +3648,10 @@ assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3397,6 +3679,10 @@ $EndFeature, " /// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true)); /// ``` #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3542,6 +3828,10 @@ assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!( ```"), #[inline] #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] pub const fn overflowing_neg(self) -> (Self, bool) { ((!self).wrapping_add(1), self != 0) } @@ -3565,6 +3855,10 @@ Basic usage assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3591,6 +3885,10 @@ Basic usage assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, " ```"), #[stable(feature = "wrapping", since = "1.7.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0"), + )] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3756,6 +4054,10 @@ Basic usage: assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0"), + )] #[inline] pub const fn is_power_of_two(self) -> bool { self.count_ones() == 1 @@ -3775,11 +4077,11 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } - // Because `p > 0`, it cannot consist entirely of leading zeros. + let p = self - 1; + // SAFETY: Because `p > 0`, it cannot consist entirely of leading zeros. // That means the shift is always in-bounds, and some processors // (such as intel pre-haswell) have more efficient ctlz // intrinsics when the argument is non-zero. - let p = self - 1; let z = unsafe { intrinsics::ctlz_nonzero(p) }; <$SelfT>::max_value() >> z } @@ -3867,7 +4169,11 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -3887,7 +4193,11 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -3922,9 +4232,15 @@ assert_eq!( ); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { + // SAFETY: integers are plain old datatypes so we can always transmute them to + // arrays of bytes unsafe { mem::transmute(self) } } } @@ -3954,7 +4270,11 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -3987,7 +4307,11 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -4030,9 +4354,14 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_int_conversion"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_int_conversion", issue = "53718"), + )] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { + // SAFETY: integers are plain old datatypes so we can always transmute to them unsafe { mem::transmute(bytes) } } } @@ -4042,8 +4371,7 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), #[lang = "u8"] impl u8 { uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", - "[0x12]", "", "" } - + "[0x12]", "", "" } /// Checks if the value is within the ASCII range. /// @@ -4209,7 +4537,7 @@ impl u8 { pub fn is_ascii_alphabetic(&self) -> bool { match *self { b'A'..=b'Z' | b'a'..=b'z' => true, - _ => false + _ => false, } } @@ -4244,7 +4572,7 @@ impl u8 { pub fn is_ascii_uppercase(&self) -> bool { match *self { b'A'..=b'Z' => true, - _ => false + _ => false, } } @@ -4279,7 +4607,7 @@ impl u8 { pub fn is_ascii_lowercase(&self) -> bool { match *self { b'a'..=b'z' => true, - _ => false + _ => false, } } @@ -4317,7 +4645,7 @@ impl u8 { pub fn is_ascii_alphanumeric(&self) -> bool { match *self { b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' => true, - _ => false + _ => false, } } @@ -4352,7 +4680,7 @@ impl u8 { pub fn is_ascii_digit(&self) -> bool { match *self { b'0'..=b'9' => true, - _ => false + _ => false, } } @@ -4390,7 +4718,7 @@ impl u8 { pub fn is_ascii_hexdigit(&self) -> bool { match *self { b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f' => true, - _ => false + _ => false, } } @@ -4429,7 +4757,7 @@ impl u8 { pub fn is_ascii_punctuation(&self) -> bool { match *self { b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~' => true, - _ => false + _ => false, } } @@ -4464,7 +4792,7 @@ impl u8 { pub fn is_ascii_graphic(&self) -> bool { match *self { b'!'..=b'~' => true, - _ => false + _ => false, } } @@ -4516,7 +4844,7 @@ impl u8 { pub fn is_ascii_whitespace(&self) -> bool { match *self { b'\t' | b'\n' | b'\x0C' | b'\r' | b' ' => true, - _ => false + _ => false, } } @@ -4553,7 +4881,7 @@ impl u8 { pub fn is_ascii_control(&self) -> bool { match *self { b'\0'..=b'\x1F' | b'\x7F' => true, - _ => false + _ => false, } } } @@ -4561,59 +4889,59 @@ impl u8 { #[lang = "u16"] impl u16 { uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]", "", "" } + "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "u32"] impl u32 { uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "u64"] impl u64 { uint_impl! { u64, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", - "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", - "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - "", ""} + "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", + "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + "", ""} } #[lang = "u128"] impl u128 { uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "", "", 16, - "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", - "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", - "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ - 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ - 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", - "", ""} + "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", + "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", + "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ + 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ + 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", + "", ""} } #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { uint_impl! { usize, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", - "[0x34, 0x12]", "[0x12, 0x34]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + "[0x34, 0x12]", "[0x12, 0x34]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678", - "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } #[cfg(target_pointer_width = "64")] #[lang = "usize"] impl usize { uint_impl! { usize, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa", - "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", - "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", - "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", - usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } + "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", + "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", + "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", + usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } /// A classification of floating point numbers. @@ -4682,13 +5010,15 @@ from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } /// The error type returned when a checked integral type conversion fails. #[stable(feature = "try_from", since = "1.34.0")] #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct TryFromIntError(()); +pub struct TryFromIntError(pub(crate) ()); impl TryFromIntError { - #[unstable(feature = "int_error_internals", - reason = "available through Error trait and this method should \ - not be exposed publicly", - issue = "0")] + #[unstable( + feature = "int_error_internals", + reason = "available through Error trait and this method should \ + not be exposed publicly", + issue = "0" + )] #[doc(hidden)] pub fn __description(&self) -> &str { "out of range integral type conversion attempted" @@ -4719,206 +5049,6 @@ impl From for TryFromIntError { } } -// no possible bounds violation -macro_rules! try_from_unbounded { - ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.34.0")] - impl TryFrom<$source> for $target { - type Error = TryFromIntError; - - /// Try to create the target number type from a source - /// number type. This returns an error if the source value - /// is outside of the range of the target type. - #[inline] - fn try_from(value: $source) -> Result { - Ok(value as $target) - } - } - )*} -} - -// only negative bounds -macro_rules! try_from_lower_bounded { - ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.34.0")] - impl TryFrom<$source> for $target { - type Error = TryFromIntError; - - /// Try to create the target number type from a source - /// number type. This returns an error if the source value - /// is outside of the range of the target type. - #[inline] - fn try_from(u: $source) -> Result<$target, TryFromIntError> { - if u >= 0 { - Ok(u as $target) - } else { - Err(TryFromIntError(())) - } - } - } - )*} -} - -// unsigned to signed (only positive bound) -macro_rules! try_from_upper_bounded { - ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.34.0")] - impl TryFrom<$source> for $target { - type Error = TryFromIntError; - - /// Try to create the target number type from a source - /// number type. This returns an error if the source value - /// is outside of the range of the target type. - #[inline] - fn try_from(u: $source) -> Result<$target, TryFromIntError> { - if u > (<$target>::max_value() as $source) { - Err(TryFromIntError(())) - } else { - Ok(u as $target) - } - } - } - )*} -} - -// all other cases -macro_rules! try_from_both_bounded { - ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.34.0")] - impl TryFrom<$source> for $target { - type Error = TryFromIntError; - - /// Try to create the target number type from a source - /// number type. This returns an error if the source value - /// is outside of the range of the target type. - #[inline] - fn try_from(u: $source) -> Result<$target, TryFromIntError> { - let min = <$target>::min_value() as $source; - let max = <$target>::max_value() as $source; - if u < min || u > max { - Err(TryFromIntError(())) - } else { - Ok(u as $target) - } - } - } - )*} -} - -macro_rules! rev { - ($mac:ident, $source:ty, $($target:ty),*) => {$( - $mac!($target, $source); - )*} -} - -// intra-sign conversions -try_from_upper_bounded!(u16, u8); -try_from_upper_bounded!(u32, u16, u8); -try_from_upper_bounded!(u64, u32, u16, u8); -try_from_upper_bounded!(u128, u64, u32, u16, u8); - -try_from_both_bounded!(i16, i8); -try_from_both_bounded!(i32, i16, i8); -try_from_both_bounded!(i64, i32, i16, i8); -try_from_both_bounded!(i128, i64, i32, i16, i8); - -// unsigned-to-signed -try_from_upper_bounded!(u8, i8); -try_from_upper_bounded!(u16, i8, i16); -try_from_upper_bounded!(u32, i8, i16, i32); -try_from_upper_bounded!(u64, i8, i16, i32, i64); -try_from_upper_bounded!(u128, i8, i16, i32, i64, i128); - -// signed-to-unsigned -try_from_lower_bounded!(i8, u8, u16, u32, u64, u128); -try_from_lower_bounded!(i16, u16, u32, u64, u128); -try_from_lower_bounded!(i32, u32, u64, u128); -try_from_lower_bounded!(i64, u64, u128); -try_from_lower_bounded!(i128, u128); -try_from_both_bounded!(i16, u8); -try_from_both_bounded!(i32, u16, u8); -try_from_both_bounded!(i64, u32, u16, u8); -try_from_both_bounded!(i128, u64, u32, u16, u8); - -// usize/isize -try_from_upper_bounded!(usize, isize); -try_from_lower_bounded!(isize, usize); - -#[cfg(target_pointer_width = "16")] -mod ptr_try_from_impls { - use super::TryFromIntError; - use crate::convert::TryFrom; - - try_from_upper_bounded!(usize, u8); - try_from_unbounded!(usize, u16, u32, u64, u128); - try_from_upper_bounded!(usize, i8, i16); - try_from_unbounded!(usize, i32, i64, i128); - - try_from_both_bounded!(isize, u8); - try_from_lower_bounded!(isize, u16, u32, u64, u128); - try_from_both_bounded!(isize, i8); - try_from_unbounded!(isize, i16, i32, i64, i128); - - rev!(try_from_upper_bounded, usize, u32, u64, u128); - rev!(try_from_lower_bounded, usize, i8, i16); - rev!(try_from_both_bounded, usize, i32, i64, i128); - - rev!(try_from_upper_bounded, isize, u16, u32, u64, u128); - rev!(try_from_both_bounded, isize, i32, i64, i128); -} - -#[cfg(target_pointer_width = "32")] -mod ptr_try_from_impls { - use super::TryFromIntError; - use crate::convert::TryFrom; - - try_from_upper_bounded!(usize, u8, u16); - try_from_unbounded!(usize, u32, u64, u128); - try_from_upper_bounded!(usize, i8, i16, i32); - try_from_unbounded!(usize, i64, i128); - - try_from_both_bounded!(isize, u8, u16); - try_from_lower_bounded!(isize, u32, u64, u128); - try_from_both_bounded!(isize, i8, i16); - try_from_unbounded!(isize, i32, i64, i128); - - rev!(try_from_unbounded, usize, u32); - rev!(try_from_upper_bounded, usize, u64, u128); - rev!(try_from_lower_bounded, usize, i8, i16, i32); - rev!(try_from_both_bounded, usize, i64, i128); - - rev!(try_from_unbounded, isize, u16); - rev!(try_from_upper_bounded, isize, u32, u64, u128); - rev!(try_from_unbounded, isize, i32); - rev!(try_from_both_bounded, isize, i64, i128); -} - -#[cfg(target_pointer_width = "64")] -mod ptr_try_from_impls { - use super::TryFromIntError; - use crate::convert::TryFrom; - - try_from_upper_bounded!(usize, u8, u16, u32); - try_from_unbounded!(usize, u64, u128); - try_from_upper_bounded!(usize, i8, i16, i32, i64); - try_from_unbounded!(usize, i128); - - try_from_both_bounded!(isize, u8, u16, u32); - try_from_lower_bounded!(isize, u64, u128); - try_from_both_bounded!(isize, i8, i16, i32); - try_from_unbounded!(isize, i64, i128); - - rev!(try_from_unbounded, usize, u32, u64); - rev!(try_from_upper_bounded, usize, u128); - rev!(try_from_lower_bounded, usize, i8, i16, i32, i64); - rev!(try_from_both_bounded, usize, i128); - - rev!(try_from_unbounded, isize, u16, u32); - rev!(try_from_upper_bounded, isize, u64, u128); - rev!(try_from_unbounded, isize, i32, i64); - rev!(try_from_both_bounded, isize, i128); -} - #[doc(hidden)] trait FromStrRadixHelper: PartialOrd + Copy { fn min_value() -> Self; @@ -4957,9 +5087,11 @@ fn from_str_radix(src: &str, radix: u32) -> Result= 2 && radix <= 36, - "from_str_radix_int: must lie in the range `[2, 36]` - found {}", - radix); + assert!( + radix >= 2 && radix <= 36, + "from_str_radix_int: must lie in the range `[2, 36]` - found {}", + radix + ); if src.is_empty() { return Err(PIE { kind: Empty }); @@ -5040,10 +5172,12 @@ pub struct ParseIntError { } /// Enum to store the various types of errors that can cause parsing an integer to fail. -#[unstable(feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639")] +#[unstable( + feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639" +)] #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum IntErrorKind { @@ -5069,17 +5203,21 @@ pub enum IntErrorKind { impl ParseIntError { /// Outputs the detailed cause of parsing an integer failing. - #[unstable(feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639")] + #[unstable( + feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639" + )] pub fn kind(&self) -> &IntErrorKind { &self.kind } - #[unstable(feature = "int_error_internals", - reason = "available through Error trait and this method should \ - not be exposed publicly", - issue = "0")] + #[unstable( + feature = "int_error_internals", + reason = "available through Error trait and this method should \ + not be exposed publicly", + issue = "0" + )] #[doc(hidden)] pub fn __description(&self) -> &str { match self.kind { @@ -5101,131 +5239,3 @@ impl fmt::Display for ParseIntError { #[stable(feature = "rust1", since = "1.0.0")] pub use crate::num::dec2flt::ParseFloatError; - -// Conversion traits for primitive integer and float types -// Conversions T -> T are covered by a blanket impl and therefore excluded -// Some conversions from and to usize/isize are not implemented due to portability concerns -macro_rules! impl_from { - ($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => { - #[$attr] - #[doc = $doc] - impl From<$Small> for $Large { - #[inline] - fn from(small: $Small) -> $Large { - small as $Large - } - } - }; - ($Small: ty, $Large: ty, #[$attr:meta]) => { - impl_from!($Small, - $Large, - #[$attr], - concat!("Converts `", - stringify!($Small), - "` to `", - stringify!($Large), - "` losslessly.")); - } -} - -macro_rules! impl_from_bool { - ($target: ty, #[$attr:meta]) => { - impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `", - stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true` -values. - -# Examples - -``` -assert_eq!(", stringify!($target), "::from(true), 1); -assert_eq!(", stringify!($target), "::from(false), 0); -```")); - }; -} - -// Bool -> Any -impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] } -impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] } - -// Unsigned -> Unsigned -impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] } - -// Signed -> Signed -impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] } - -// Unsigned -> Signed -impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] } -impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] } -impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] } - -// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX -// which imply that pointer-sized integers must be at least 16 bits: -// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4 -impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } -impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } -impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } - -// RISC-V defines the possibility of a 128-bit address space (RV128). - -// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize. -// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf -// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf - - -// Note: integers can only be represented with full precision in a float if -// they fit in the significand, which is 24 bits in f32 and 53 bits in f64. -// Lossy float conversions are not implemented at this time. - -// Signed -> Float -impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } - -// Unsigned -> Float -impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } -impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } - -// Float -> Float -impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 5fe9895d8d..46398dd2f8 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -4,7 +4,7 @@ use crate::ops::*; #[allow(unused_macros)] macro_rules! sh_impl_signed { - ($t:ident, $f:ident) => ( + ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; @@ -19,7 +19,7 @@ macro_rules! sh_impl_signed { } } forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { @@ -44,7 +44,7 @@ macro_rules! sh_impl_signed { } } forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { @@ -54,11 +54,11 @@ macro_rules! sh_impl_signed { } } forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } - ) + }; } macro_rules! sh_impl_unsigned { - ($t:ident, $f:ident) => ( + ($t:ident, $f:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl Shl<$f> for Wrapping<$t> { type Output = Wrapping<$t>; @@ -69,7 +69,7 @@ macro_rules! sh_impl_unsigned { } } forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for Wrapping<$t> { @@ -90,7 +90,7 @@ macro_rules! sh_impl_unsigned { } } forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f, - #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } + #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for Wrapping<$t> { @@ -100,7 +100,7 @@ macro_rules! sh_impl_unsigned { } } forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f } - ) + }; } // FIXME (#23545): uncomment the remaining impls @@ -530,6 +530,10 @@ assert_eq!(n.trailing_zeros(), 3); /// assert_eq!(m, Wrapping(-22016)); /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0"), + )] #[inline] #[must_use] pub const fn reverse_bits(self) -> Self { diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 3c009d644c..59a72799e2 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -66,19 +66,13 @@ #[lang = "add"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented( - on( - all(_Self="{integer}", Rhs="{float}"), - message="cannot add a float to an integer", - ), - on( - all(_Self="{float}", Rhs="{integer}"), - message="cannot add an integer to a float", - ), - message="cannot add `{Rhs}` to `{Self}`", - label="no implementation for `{Self} + {Rhs}`", + on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",), + on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`" )] #[doc(alias = "+")] -pub trait Add { +pub trait Add { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -173,10 +167,12 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "sub"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="cannot subtract `{Rhs}` from `{Self}`", - label="no implementation for `{Self} - {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot subtract `{Rhs}` from `{Self}`", + label = "no implementation for `{Self} - {Rhs}`" +)] #[doc(alias = "-")] -pub trait Sub { +pub trait Sub { /// The resulting type after applying the `-` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -293,10 +289,12 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "mul"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="cannot multiply `{Rhs}` to `{Self}`", - label="no implementation for `{Self} * {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot multiply `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} * {Rhs}`" +)] #[doc(alias = "*")] -pub trait Mul { +pub trait Mul { /// The resulting type after applying the `*` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -417,10 +415,12 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "div"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{Rhs}`", - label="no implementation for `{Self} / {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot divide `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} / {Rhs}`" +)] #[doc(alias = "/")] -pub trait Div { +pub trait Div { /// The resulting type after applying the `/` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -502,10 +502,12 @@ div_impl_float! { f32 f64 } /// ``` #[lang = "rem"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{Rhs}`", - label="no implementation for `{Self} % {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot mod `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} % {Rhs}`" +)] #[doc(alias = "%")] -pub trait Rem { +pub trait Rem { /// The resulting type after applying the `%` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -534,7 +536,6 @@ macro_rules! rem_impl_integer { rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - macro_rules! rem_impl_float { ($($t:ty)*) => ($( @@ -616,8 +617,6 @@ pub trait Neg { fn neg(self) -> Self::Output; } - - macro_rules! neg_impl_core { ($id:ident => $body:expr, $($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] @@ -679,11 +678,13 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "add_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`", - label="no implementation for `{Self} += {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot add-assign `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} += {Rhs}`" +)] #[doc(alias = "+")] #[doc(alias = "+=")] -pub trait AddAssign { +pub trait AddAssign { /// Performs the `+=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn add_assign(&mut self, rhs: Rhs); @@ -735,11 +736,13 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "sub_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="cannot subtract-assign `{Rhs}` from `{Self}`", - label="no implementation for `{Self} -= {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot subtract-assign `{Rhs}` from `{Self}`", + label = "no implementation for `{Self} -= {Rhs}`" +)] #[doc(alias = "-")] #[doc(alias = "-=")] -pub trait SubAssign { +pub trait SubAssign { /// Performs the `-=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn sub_assign(&mut self, rhs: Rhs); @@ -782,11 +785,13 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "mul_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`", - label="no implementation for `{Self} *= {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot multiply-assign `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} *= {Rhs}`" +)] #[doc(alias = "*")] #[doc(alias = "*=")] -pub trait MulAssign { +pub trait MulAssign { /// Performs the `*=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn mul_assign(&mut self, rhs: Rhs); @@ -829,11 +834,13 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "div_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`", - label="no implementation for `{Self} /= {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot divide-assign `{Self}` by `{Rhs}`", + label = "no implementation for `{Self} /= {Rhs}`" +)] #[doc(alias = "/")] #[doc(alias = "/=")] -pub trait DivAssign { +pub trait DivAssign { /// Performs the `/=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn div_assign(&mut self, rhs: Rhs); @@ -879,11 +886,13 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "rem_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``", - label="no implementation for `{Self} %= {Rhs}`")] +#[rustc_on_unimplemented( + message = "cannot mod-assign `{Self}` by `{Rhs}``", + label = "no implementation for `{Self} %= {Rhs}`" +)] #[doc(alias = "%")] #[doc(alias = "%=")] -pub trait RemAssign { +pub trait RemAssign { /// Performs the `%=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn rem_assign(&mut self, rhs: Rhs); diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index a8f862f6c0..bcfff4a223 100644 --- a/src/libcore/ops/bit.rs +++ b/src/libcore/ops/bit.rs @@ -112,9 +112,11 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitand"] #[doc(alias = "&")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} & {Rhs}`", - label="no implementation for `{Self} & {Rhs}`")] -pub trait BitAnd { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} & {Rhs}`", + label = "no implementation for `{Self} & {Rhs}`" +)] +pub trait BitAnd { /// The resulting type after applying the `&` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -196,9 +198,11 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitor"] #[doc(alias = "|")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} | {Rhs}`", - label="no implementation for `{Self} | {Rhs}`")] -pub trait BitOr { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} | {Rhs}`", + label = "no implementation for `{Self} | {Rhs}`" +)] +pub trait BitOr { /// The resulting type after applying the `|` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -283,9 +287,11 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitxor"] #[doc(alias = "^")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {Rhs}`", - label="no implementation for `{Self} ^ {Rhs}`")] -pub trait BitXor { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} ^ {Rhs}`", + label = "no implementation for `{Self} ^ {Rhs}`" +)] +pub trait BitXor { /// The resulting type after applying the `^` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -371,9 +377,11 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "shl"] #[doc(alias = "<<")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} << {Rhs}`", - label="no implementation for `{Self} << {Rhs}`")] -pub trait Shl { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} << {Rhs}`", + label = "no implementation for `{Self} << {Rhs}`" +)] +pub trait Shl { /// The resulting type after applying the `<<` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -385,7 +393,7 @@ pub trait Shl { } macro_rules! shl_impl { - ($t:ty, $f:ty) => ( + ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] impl Shl<$f> for $t { type Output = $t; @@ -398,7 +406,7 @@ macro_rules! shl_impl { } forward_ref_binop! { impl Shl, shl for $t, $f } - ) + }; } macro_rules! shl_impl_all { @@ -480,9 +488,11 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } #[lang = "shr"] #[doc(alias = ">>")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} >> {Rhs}`", - label="no implementation for `{Self} >> {Rhs}`")] -pub trait Shr { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} >> {Rhs}`", + label = "no implementation for `{Self} >> {Rhs}`" +)] +pub trait Shr { /// The resulting type after applying the `>>` operator. #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -494,7 +504,7 @@ pub trait Shr { } macro_rules! shr_impl { - ($t:ty, $f:ty) => ( + ($t:ty, $f:ty) => { #[stable(feature = "rust1", since = "1.0.0")] impl Shr<$f> for $t { type Output = $t; @@ -507,7 +517,7 @@ macro_rules! shr_impl { } forward_ref_binop! { impl Shr, shr for $t, $f } - ) + }; } macro_rules! shr_impl_all { @@ -596,9 +606,11 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } #[lang = "bitand_assign"] #[doc(alias = "&=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`", - label="no implementation for `{Self} &= {Rhs}`")] -pub trait BitAndAssign { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} &= {Rhs}`", + label = "no implementation for `{Self} &= {Rhs}`" +)] +pub trait BitAndAssign { /// Performs the `&=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn bitand_assign(&mut self, rhs: Rhs); @@ -645,9 +657,11 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitor_assign"] #[doc(alias = "|=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`", - label="no implementation for `{Self} |= {Rhs}`")] -pub trait BitOrAssign { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} |= {Rhs}`", + label = "no implementation for `{Self} |= {Rhs}`" +)] +pub trait BitOrAssign { /// Performs the `|=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn bitor_assign(&mut self, rhs: Rhs); @@ -694,9 +708,11 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitxor_assign"] #[doc(alias = "^=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`", - label="no implementation for `{Self} ^= {Rhs}`")] -pub trait BitXorAssign { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} ^= {Rhs}`", + label = "no implementation for `{Self} ^= {Rhs}`" +)] +pub trait BitXorAssign { /// Performs the `^=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn bitxor_assign(&mut self, rhs: Rhs); @@ -741,16 +757,18 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "shl_assign"] #[doc(alias = "<<=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`", - label="no implementation for `{Self} <<= {Rhs}`")] -pub trait ShlAssign { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} <<= {Rhs}`", + label = "no implementation for `{Self} <<= {Rhs}`" +)] +pub trait ShlAssign { /// Performs the `<<=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn shl_assign(&mut self, rhs: Rhs); } macro_rules! shl_assign_impl { - ($t:ty, $f:ty) => ( + ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShlAssign<$f> for $t { #[inline] @@ -761,7 +779,7 @@ macro_rules! shl_assign_impl { } forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f } - ) + }; } macro_rules! shl_assign_impl_all { @@ -809,16 +827,18 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } #[lang = "shr_assign"] #[doc(alias = ">>=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`", - label="no implementation for `{Self} >>= {Rhs}`")] -pub trait ShrAssign { +#[rustc_on_unimplemented( + message = "no implementation for `{Self} >>= {Rhs}`", + label = "no implementation for `{Self} >>= {Rhs}`" +)] +pub trait ShrAssign { /// Performs the `>>=` operation. #[stable(feature = "op_assign_traits", since = "1.8.0")] fn shr_assign(&mut self, rhs: Rhs); } macro_rules! shr_assign_impl { - ($t:ty, $f:ty) => ( + ($t:ty, $f:ty) => { #[stable(feature = "op_assign_traits", since = "1.8.0")] impl ShrAssign<$f> for $t { #[inline] @@ -829,7 +849,7 @@ macro_rules! shr_assign_impl { } forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f } - ) + }; } macro_rules! shr_assign_impl_all { diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index ce0d3fd01f..f521355a90 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -76,14 +76,18 @@ pub trait Deref { impl Deref for &T { type Target = T; - fn deref(&self) -> &T { *self } + fn deref(&self) -> &T { + *self + } } #[stable(feature = "rust1", since = "1.0.0")] impl Deref for &mut T { type Target = T; - fn deref(&self) -> &T { *self } + fn deref(&self) -> &T { + *self + } } /// Used for mutable dereferencing operations, like in `*v = 1;`. @@ -165,7 +169,9 @@ pub trait DerefMut: Deref { #[stable(feature = "rust1", since = "1.0.0")] impl DerefMut for &mut T { - fn deref_mut(&mut self) -> &mut T { *self } + fn deref_mut(&mut self) -> &mut T { + *self + } } /// Indicates that a struct can be used as a method receiver, without the diff --git a/src/libcore/ops/function.rs b/src/libcore/ops/function.rs index 4a0a2720fe..505a65cee3 100644 --- a/src/libcore/ops/function.rs +++ b/src/libcore/ops/function.rs @@ -57,13 +57,16 @@ #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] #[rustc_on_unimplemented( - on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"), - message="expected a `{Fn}<{Args}>` closure, found `{Self}`", - label="expected an `Fn<{Args}>` closure, found `{Self}`", + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}" + ), + message = "expected a `{Fn}<{Args}>` closure, found `{Self}`", + label = "expected an `Fn<{Args}>` closure, found `{Self}`" )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -pub trait Fn : FnMut { +pub trait Fn: FnMut { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call(&self, args: Args) -> Self::Output; @@ -136,17 +139,16 @@ pub trait Fn : FnMut { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] #[rustc_on_unimplemented( - on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"), on( - all(Args="(char,)", _Self="std::string::String"), - note="borrowing the `{Self}` might fix the problem" + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}" ), - message="expected a `{FnMut}<{Args}>` closure, found `{Self}`", - label="expected an `FnMut<{Args}>` closure, found `{Self}`", + message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`", + label = "expected an `FnMut<{Args}>` closure, found `{Self}`" )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] -pub trait FnMut : FnOnce { +pub trait FnMut: FnOnce { /// Performs the call operation. #[unstable(feature = "fn_traits", issue = "29625")] extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; @@ -211,9 +213,12 @@ pub trait FnMut : FnOnce { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] #[rustc_on_unimplemented( - on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"), - message="expected a `{FnOnce}<{Args}>` closure, found `{Self}`", - label="expected an `FnOnce<{Args}>` closure, found `{Self}`", + on( + Args = "()", + note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}" + ), + message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`", + label = "expected an `FnOnce<{Args}>` closure, found `{Self}`" )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] @@ -229,8 +234,9 @@ pub trait FnOnce { mod impls { #[stable(feature = "rust1", since = "1.0.0")] - impl Fn for &F - where F : Fn + impl Fn for &F + where + F: Fn, { extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) @@ -238,8 +244,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &F - where F : Fn + impl FnMut for &F + where + F: Fn, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) @@ -247,8 +254,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &F - where F : Fn + impl FnOnce for &F + where + F: Fn, { type Output = F::Output; @@ -258,8 +266,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnMut for &mut F - where F : FnMut + impl FnMut for &mut F + where + F: FnMut, { extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) @@ -267,8 +276,9 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl FnOnce for &mut F - where F : FnMut + impl FnOnce for &mut F + where + F: FnMut, { type Output = F::Output; extern "rust-call" fn call_once(self, args: A) -> F::Output { diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs index 9cff474a76..aae0691122 100644 --- a/src/libcore/ops/index.rs +++ b/src/libcore/ops/index.rs @@ -51,8 +51,8 @@ /// ``` #[lang = "index"] #[rustc_on_unimplemented( - message="the type `{Self}` cannot be indexed by `{Idx}`", - label="`{Self}` cannot be indexed by `{Idx}`", + message = "the type `{Self}` cannot be indexed by `{Idx}`", + label = "`{Self}` cannot be indexed by `{Idx}`" )] #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "]")] @@ -142,22 +142,22 @@ pub trait Index { #[lang = "index_mut"] #[rustc_on_unimplemented( on( - _Self="&str", - note="you can use `.chars().nth()` or `.bytes().nth()` + _Self = "&str", + note = "you can use `.chars().nth()` or `.bytes().nth()` see chapter in The Book " ), on( - _Self="str", - note="you can use `.chars().nth()` or `.bytes().nth()` + _Self = "str", + note = "you can use `.chars().nth()` or `.bytes().nth()` see chapter in The Book " ), on( - _Self="std::string::String", - note="you can use `.chars().nth()` or `.bytes().nth()` + _Self = "std::string::String", + note = "you can use `.chars().nth()` or `.bytes().nth()` see chapter in The Book " ), - message="the type `{Self}` cannot be mutably indexed by `{Idx}`", - label="`{Self}` cannot be mutably indexed by `{Idx}`", + message = "the type `{Self}` cannot be mutably indexed by `{Idx}`", + label = "`{Self}` cannot be mutably indexed by `{Idx}`" )] #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "[")] diff --git a/src/libcore/ops/mod.rs b/src/libcore/ops/mod.rs index 5d1d3efd41..80ab906961 100644 --- a/src/libcore/ops/mod.rs +++ b/src/libcore/ops/mod.rs @@ -156,12 +156,12 @@ mod r#try; mod unsize; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg}; +pub use self::arith::{Add, Div, Mul, Neg, Rem, Sub}; #[stable(feature = "op_assign_traits", since = "1.8.0")] -pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +pub use self::arith::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign}; #[stable(feature = "rust1", since = "1.0.0")] -pub use self::bit::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; +pub use self::bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; #[stable(feature = "op_assign_traits", since = "1.8.0")] pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; @@ -184,7 +184,7 @@ pub use self::index::{Index, IndexMut}; pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[stable(feature = "inclusive_range", since = "1.26.0")] -pub use self::range::{RangeInclusive, RangeToInclusive, RangeBounds, Bound}; +pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; #[unstable(feature = "try_trait", issue = "42327")] pub use self::r#try::Try; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 1b4c4218cc..54ce2917a3 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -398,12 +398,9 @@ impl RangeInclusive { #[stable(feature = "inclusive_range_methods", since = "1.27.0")] #[inline] #[rustc_promotable] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_range_new", since = "1.32.0"))] pub const fn new(start: Idx, end: Idx) -> Self { - Self { - start, - end, - is_empty: None, - } + Self { start, end, is_empty: None } } /// Returns the lower bound of the range (inclusive). @@ -425,6 +422,10 @@ impl RangeInclusive { /// assert_eq!((3..=5).start(), &3); /// ``` #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0"), + )] #[inline] pub const fn start(&self) -> &Idx { &self.start @@ -449,6 +450,10 @@ impl RangeInclusive { /// assert_eq!((3..=5).end(), &5); /// ``` #[stable(feature = "inclusive_range_methods", since = "1.27.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0"), + )] #[inline] pub const fn end(&self) -> &Idx { &self.end diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index e8f35f8cf2..22ba97b91d 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -5,32 +5,28 @@ /// extracting those success or failure values from an existing instance and /// creating a new instance from a success or failure value. #[unstable(feature = "try_trait", issue = "42327")] -#[cfg_attr(bootstrap, rustc_on_unimplemented( - on(all( - any(from_method="from_error", from_method="from_ok"), - from_desugaring="QuestionMark"), - message="the `?` operator can only be used in a \ - function that returns `Result` or `Option` \ - (or another type that implements `{Try}`)", - label="cannot use the `?` operator in a function that returns `{Self}`"), - on(all(from_method="into_result", from_desugaring="QuestionMark"), - message="the `?` operator can only be applied to values \ - that implement `{Try}`", - label="the `?` operator cannot be applied to type `{Self}`") -))] -#[cfg_attr(not(bootstrap), rustc_on_unimplemented( -on(all( -any(from_method="from_error", from_method="from_ok"), -from_desugaring="QuestionMark"), -message="the `?` operator can only be used in {ItemContext} \ - that returns `Result` or `Option` \ - (or another type that implements `{Try}`)", -label="cannot use the `?` operator in {ItemContext} that returns `{Self}`"), -on(all(from_method="into_result", from_desugaring="QuestionMark"), -message="the `?` operator can only be applied to values \ - that implement `{Try}`", -label="the `?` operator cannot be applied to type `{Self}`") -))] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + on( + all( + any(from_method = "from_error", from_method = "from_ok"), + from_desugaring = "QuestionMark" + ), + message = "the `?` operator can only be used in {ItemContext} \ + that returns `Result` or `Option` \ + (or another type that implements `{Try}`)", + label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", + enclosing_scope = "this function should return `Result` or `Option` to accept `?`" + ), + on( + all(from_method = "into_result", from_desugaring = "QuestionMark"), + message = "the `?` operator can only be applied to values \ + that implement `{Try}`", + label = "the `?` operator cannot be applied to type `{Self}`" + ) + ) +)] #[doc(alias = "?")] pub trait Try { /// The type of this value when viewed as successful. diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs index d29147645f..80fb5642a6 100644 --- a/src/libcore/ops/unsize.rs +++ b/src/libcore/ops/unsize.rs @@ -39,35 +39,34 @@ pub trait CoerceUnsized { // &mut T -> &mut U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} // &mut T -> &U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} // &mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} // &mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} // &T -> &U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} // &T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} // *mut T -> *mut U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} // *mut T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} +impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} // *const T -> *const U #[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} - +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// This is used for object safety, to check that a method's receiver type can be dispatched on. /// @@ -90,13 +89,13 @@ pub trait DispatchFromDyn { // &T -> &U #[unstable(feature = "dispatch_from_dyn", issue = "0")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} // &mut T -> &mut U #[unstable(feature = "dispatch_from_dyn", issue = "0")] -impl<'a, T: ?Sized+Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} // *const T -> *const U #[unstable(feature = "dispatch_from_dyn", issue = "0")] -impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} +impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} // *mut T -> *mut U #[unstable(feature = "dispatch_from_dyn", issue = "0")] -impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} +impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index f0ac5e749f..2066a484da 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -133,11 +133,16 @@ //! [`Box`]: ../../std/boxed/struct.Box.html //! [`i32`]: ../../std/primitive.i32.html +// ignore-tidy-undocumented-unsafe + #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{FromIterator, FusedIterator, TrustedLen}; -use crate::{convert, fmt, hint, mem, ops::{self, Deref, DerefMut}}; use crate::pin::Pin; +use crate::{ + convert, fmt, hint, mem, + ops::{self, Deref, DerefMut}, +}; // Note that this is not a lang item per se, but it has a hidden dependency on // `Iterator`, which is one. The compiler assumes that the `next` method of @@ -228,7 +233,10 @@ impl Option { #[must_use] #[inline] #[unstable(feature = "option_result_contains", issue = "62358")] - pub fn contains(&self, x: &U) -> bool where U: PartialEq { + pub fn contains(&self, x: &U) -> bool + where + U: PartialEq, + { match self { Some(y) => x == y, None => false, @@ -289,16 +297,13 @@ impl Option { } } - /// Converts from [`Pin`]`<&Option>` to `Option<`[`Pin`]`<&T>>`. /// /// [`Pin`]: ../pin/struct.Pin.html #[inline] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_ref(self: Pin<&Self>) -> Option> { - unsafe { - Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) - } + unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) } } /// Converts from [`Pin`]`<&mut Option>` to `Option<`[`Pin`]`<&mut T>>`. @@ -307,9 +312,7 @@ impl Option { #[inline] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_mut(self: Pin<&mut Self>) -> Option> { - unsafe { - Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) - } + unsafe { Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) } } ///////////////////////////////////////////////////////////////////////// @@ -688,7 +691,7 @@ impl Option { pub fn filter bool>(self, predicate: P) -> Self { if let Some(x) = self { if predicate(&x) { - return Some(x) + return Some(x); } } None @@ -1226,7 +1229,9 @@ impl Default for Option { /// assert!(opt.is_none()); /// ``` #[inline] - fn default() -> Option { None } + fn default() -> Option { + None + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1300,7 +1305,7 @@ impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { #[derive(Clone, Debug)] struct Item { - opt: Option + opt: Option, } impl Iterator for Item { @@ -1342,22 +1347,30 @@ unsafe impl TrustedLen for Item {} /// [`Option::iter`]: enum.Option.html#method.iter #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] -pub struct Iter<'a, A: 'a> { inner: Item<&'a A> } +pub struct Iter<'a, A: 'a> { + inner: Item<&'a A>, +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> Iterator for Iter<'a, A> { type Item = &'a A; #[inline] - fn next(&mut self) -> Option<&'a A> { self.inner.next() } + fn next(&mut self) -> Option<&'a A> { + self.inner.next() + } #[inline] - fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> DoubleEndedIterator for Iter<'a, A> { #[inline] - fn next_back(&mut self) -> Option<&'a A> { self.inner.next_back() } + fn next_back(&mut self) -> Option<&'a A> { + self.inner.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1388,22 +1401,30 @@ impl Clone for Iter<'_, A> { /// [`Option::iter_mut`]: enum.Option.html#method.iter_mut #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] -pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> } +pub struct IterMut<'a, A: 'a> { + inner: Item<&'a mut A>, +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> Iterator for IterMut<'a, A> { type Item = &'a mut A; #[inline] - fn next(&mut self) -> Option<&'a mut A> { self.inner.next() } + fn next(&mut self) -> Option<&'a mut A> { + self.inner.next() + } #[inline] - fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> DoubleEndedIterator for IterMut<'a, A> { #[inline] - fn next_back(&mut self) -> Option<&'a mut A> { self.inner.next_back() } + fn next_back(&mut self) -> Option<&'a mut A> { + self.inner.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1425,22 +1446,30 @@ unsafe impl TrustedLen for IterMut<'_, A> {} /// [`Option::into_iter`]: enum.Option.html#method.into_iter #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { inner: Item } +pub struct IntoIter { + inner: Item, +} #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = A; #[inline] - fn next(&mut self) -> Option { self.inner.next() } + fn next(&mut self) -> Option { + self.inner.next() + } #[inline] - fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for IntoIter { #[inline] - fn next_back(&mut self) -> Option { self.inner.next_back() } + fn next_back(&mut self) -> Option { + self.inner.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1521,14 +1550,11 @@ impl> FromIterator> for Option { /// /// [`Iterator`]: ../iter/trait.Iterator.html #[inline] - fn from_iter>>(iter: I) -> Option { + fn from_iter>>(iter: I) -> Option { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. - iter.into_iter() - .map(|x| x.ok_or(())) - .collect::>() - .ok() + iter.into_iter().map(|x| x.ok_or(())).collect::>().ok() } } diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 51bbf3a8fd..48bb504a73 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -1,8 +1,6 @@ //! Panic support in the standard library. -#![unstable(feature = "core_panic_info", - reason = "newly available in libcore", - issue = "44489")] +#![stable(feature = "core_panic_info", since = "1.41.0")] use crate::any::Any; use crate::fmt; @@ -39,10 +37,10 @@ pub struct PanicInfo<'a> { } impl<'a> PanicInfo<'a> { - #![unstable(feature = "panic_internals", - reason = "internal details of the implementation of the `panic!` \ - and related macros", - issue = "0")] + #[unstable(feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0")] #[doc(hidden)] #[inline] pub fn internal_constructor( @@ -57,6 +55,10 @@ impl<'a> PanicInfo<'a> { } } + #[unstable(feature = "panic_internals", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0")] #[doc(hidden)] #[inline] pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) { @@ -90,7 +92,7 @@ impl<'a> PanicInfo<'a> { /// returns that message ready to be used for example with [`fmt::write`] /// /// [`fmt::write`]: ../fmt/fn.write.html - #[unstable(feature = "panic_info_message", issue = "44489")] + #[unstable(feature = "panic_info_message", issue = "66745")] pub fn message(&self) -> Option<&fmt::Arguments<'_>> { self.message } @@ -167,7 +169,7 @@ impl fmt::Display for PanicInfo<'_> { /// /// panic!("Normal panic"); /// ``` -#[cfg_attr(not(bootstrap), lang = "panic_location")] +#[lang = "panic_location"] #[derive(Debug)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { @@ -176,6 +178,60 @@ pub struct Location<'a> { col: u32, } +impl<'a> Location<'a> { + /// Returns the source location of the caller of this function. If that function's caller is + /// annotated then its call location will be returned, and so on up the stack to the first call + /// within a non-tracked function body. + /// + /// # Examples + /// + /// ``` + /// #![feature(track_caller)] + /// use core::panic::Location; + /// + /// /// Returns the [`Location`] at which it is called. + /// #[track_caller] + /// fn get_caller_location() -> &'static Location<'static> { + /// Location::caller() + /// } + /// + /// /// Returns a [`Location`] from within this function's definition. + /// fn get_just_one_location() -> &'static Location<'static> { + /// get_caller_location() + /// } + /// + /// let fixed_location = get_just_one_location(); + /// assert_eq!(fixed_location.file(), file!()); + /// assert_eq!(fixed_location.line(), 15); + /// assert_eq!(fixed_location.column(), 5); + /// + /// // running the same untracked function in a different location gives us the same result + /// let second_fixed_location = get_just_one_location(); + /// assert_eq!(fixed_location.file(), second_fixed_location.file()); + /// assert_eq!(fixed_location.line(), second_fixed_location.line()); + /// assert_eq!(fixed_location.column(), second_fixed_location.column()); + /// + /// let this_location = get_caller_location(); + /// assert_eq!(this_location.file(), file!()); + /// assert_eq!(this_location.line(), 29); + /// assert_eq!(this_location.column(), 21); + /// + /// // running the tracked function in a different location produces a different value + /// let another_location = get_caller_location(); + /// assert_eq!(this_location.file(), another_location.file()); + /// assert_ne!(this_location.line(), another_location.line()); + /// assert_ne!(this_location.column(), another_location.column()); + /// ``` + #[cfg(not(bootstrap))] + #[unstable(feature = "track_caller", + reason = "uses #[track_caller] which is not yet stable", + issue = "47809")] + #[track_caller] + pub const fn caller() -> &'static Location<'static> { + crate::intrinsics::caller_location() + } +} + impl<'a> Location<'a> { #![unstable(feature = "panic_internals", reason = "internal details of the implementation of the `panic!` \ @@ -266,6 +322,16 @@ impl fmt::Display for Location<'_> { #[unstable(feature = "std_internals", issue = "0")] #[doc(hidden)] pub unsafe trait BoxMeUp { - fn box_me_up(&mut self) -> *mut (dyn Any + Send); + /// Take full ownership of the contents. + /// The return type is actually `Box`, but we cannot use `Box` in libcore. + /// + /// After this method got called, only some dummy default value is left in `self`. + /// Calling this method twice, or calling `get` after calling this method, is an error. + /// + /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only + /// gets a borrowed `dyn BoxMeUp`. + fn take_box(&mut self) -> *mut (dyn Any + Send); + + /// Just borrow the contents. fn get(&mut self) -> &(dyn Any + Send); } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 685b749776..4857b11459 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -6,56 +6,37 @@ //! interface for panicking is: //! //! ``` -//! # use std::fmt; -//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! +//! fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> ! //! # { loop {} } //! ``` //! //! This definition allows for panicking with any general message, but it does not -//! allow for failing with a `Box` value. The reason for this is that libcore -//! is not allowed to allocate. +//! allow for failing with a `Box` value. (`PanicInfo` just contains a `&(dyn Any + Send)`, +//! for which we fill in a dummy value in `PanicInfo::internal_constructor`.) +//! The reason for this is that libcore is not allowed to allocate. //! //! This module contains a few other panicking functions, but these are just the //! necessary lang items for the compiler. All panics are funneled through this -//! one function. Currently, the actual symbol is declared in the standard -//! library, but the location of this may change over time. +//! one function. The actual symbol is declared through the `#[panic_handler]` attribute. + +// ignore-tidy-undocumented-unsafe #![allow(dead_code, missing_docs)] -#![unstable(feature = "core_panic", - reason = "internal details of the implementation of the `panic!` \ - and related macros", - issue = "0")] +#![unstable( + feature = "core_panic", + reason = "internal details of the implementation of the `panic!` \ + and related macros", + issue = "0" +)] use crate::fmt; use crate::panic::{Location, PanicInfo}; -#[cfg(bootstrap)] #[cold] // never inline unless panic_immediate_abort to avoid code // bloat at the call sites as much as possible -#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] -#[lang = "panic"] -pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! { - if cfg!(feature = "panic_immediate_abort") { - unsafe { super::intrinsics::abort() } - } - - // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially - // reduce size overhead. The format_args! macro uses str's Display trait to - // write expr, which calls Formatter::pad, which must accommodate string - // truncation and padding (even though none is used here). Using - // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the - // output binary, saving up to a few kilobytes. - let (expr, file, line, col) = *expr_file_line_col; - panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col)) -} - -#[cfg(not(bootstrap))] -#[cold] -// never inline unless panic_immediate_abort to avoid code -// bloat at the call sites as much as possible -#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] -#[lang = "panic"] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators pub fn panic(expr: &str, location: &Location<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { unsafe { super::intrinsics::abort() } @@ -70,24 +51,9 @@ pub fn panic(expr: &str, location: &Location<'_>) -> ! { panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location) } -#[cfg(bootstrap)] #[cold] -#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] -#[lang = "panic_bounds_check"] -fn panic_bounds_check(file_line_col: &(&'static str, u32, u32), - index: usize, len: usize) -> ! { - if cfg!(feature = "panic_immediate_abort") { - unsafe { super::intrinsics::abort() } - } - - panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", - len, index), file_line_col) -} - -#[cfg(not(bootstrap))] -#[cold] -#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] -#[lang = "panic_bounds_check"] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! { if cfg!(feature = "panic_immediate_abort") { unsafe { super::intrinsics::abort() } @@ -95,41 +61,20 @@ fn panic_bounds_check(location: &Location<'_>, index: usize, len: usize) -> ! { panic_fmt( format_args!("index out of bounds: the len is {} but the index is {}", len, index), - location + location, ) } -#[cfg(bootstrap)] -#[cold] -#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] -#[cfg_attr( feature="panic_immediate_abort" ,inline)] -pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u32)) -> ! { - if cfg!(feature = "panic_immediate_abort") { - unsafe { super::intrinsics::abort() } - } - - // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - extern "Rust" { - #[lang = "panic_impl"] - fn panic_impl(pi: &PanicInfo<'_>) -> !; - } - - let (file, line, col) = *file_line_col; - let location = Location::internal_constructor(file, line, col); - let pi = PanicInfo::internal_constructor(Some(&fmt), &location); - unsafe { panic_impl(&pi) } -} - -#[cfg(not(bootstrap))] #[cold] -#[cfg_attr(not(feature="panic_immediate_abort"),inline(never))] -#[cfg_attr( feature="panic_immediate_abort" ,inline)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] pub fn panic_fmt(fmt: fmt::Arguments<'_>, location: &Location<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { unsafe { super::intrinsics::abort() } } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index be057ed6d5..6a0c5bbebc 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -374,10 +374,11 @@ #![stable(feature = "pin", since = "1.33.0")] +use crate::cmp::{self, PartialEq, PartialOrd}; use crate::fmt; +use crate::hash::{Hash, Hasher}; use crate::marker::{Sized, Unpin}; -use crate::cmp::{self, PartialEq, PartialOrd}; -use crate::ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; /// A pinned pointer. /// @@ -390,55 +391,78 @@ use crate::ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html // -// Note: the derives below, and the explicit `PartialEq` and `PartialOrd` -// implementations, are allowed because they all only use `&P`, so they cannot move -// the value behind `pointer`. +// Note: the `Clone` derive below causes unsoundness as it's possible to implement +// `Clone` for mutable references. +// See for more details. #[stable(feature = "pin", since = "1.33.0")] #[lang = "pin"] #[fundamental] #[repr(transparent)] -#[derive(Copy, Clone, Hash, Eq, Ord)] +#[derive(Copy, Clone)] pub struct Pin

{ pointer: P, } -#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] -impl PartialEq> for Pin

+// The following implementations aren't derived in order to avoid soundness +// issues. `&self.pointer` should not be accessible to untrusted trait +// implementations. +// +// See for more details. + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl PartialEq> for Pin

where - P: PartialEq, + P::Target: PartialEq, { fn eq(&self, other: &Pin) -> bool { - self.pointer == other.pointer + P::Target::eq(self, other) } fn ne(&self, other: &Pin) -> bool { - self.pointer != other.pointer + P::Target::ne(self, other) } } -#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] -impl PartialOrd> for Pin

+#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl> Eq for Pin

{} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl PartialOrd> for Pin

where - P: PartialOrd, + P::Target: PartialOrd, { fn partial_cmp(&self, other: &Pin) -> Option { - self.pointer.partial_cmp(&other.pointer) + P::Target::partial_cmp(self, other) } fn lt(&self, other: &Pin) -> bool { - self.pointer < other.pointer + P::Target::lt(self, other) } fn le(&self, other: &Pin) -> bool { - self.pointer <= other.pointer + P::Target::le(self, other) } fn gt(&self, other: &Pin) -> bool { - self.pointer > other.pointer + P::Target::gt(self, other) } fn ge(&self, other: &Pin) -> bool { - self.pointer >= other.pointer + P::Target::ge(self, other) + } +} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl> Ord for Pin

{ + fn cmp(&self, other: &Self) -> cmp::Ordering { + P::Target::cmp(self, other) + } +} + +#[stable(feature = "pin_trait_impls", since = "1.41.0")] +impl> Hash for Pin

{ + fn hash(&self, state: &mut H) { + P::Target::hash(self, state); } } @@ -552,6 +576,7 @@ impl Pin

{ #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_ref(&self) -> Pin<&P::Target> { + // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&*self.pointer) } } @@ -610,6 +635,7 @@ impl Pin

{ #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_mut(&mut self) -> Pin<&mut P::Target> { + // SAFETY: see documentation on this function unsafe { Pin::new_unchecked(&mut *self.pointer) } } @@ -644,7 +670,8 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] - pub unsafe fn map_unchecked(self, func: F) -> Pin<&'a U> where + pub unsafe fn map_unchecked(self, func: F) -> Pin<&'a U> + where F: FnOnce(&T) -> &U, { let pointer = &*self.pointer; @@ -696,7 +723,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn get_mut(self) -> &'a mut T - where T: Unpin, + where + T: Unpin, { self.pointer } @@ -733,7 +761,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// /// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning #[stable(feature = "pin", since = "1.33.0")] - pub unsafe fn map_unchecked_mut(self, func: F) -> Pin<&'a mut U> where + pub unsafe fn map_unchecked_mut(self, func: F) -> Pin<&'a mut U> + where F: FnOnce(&mut T) -> &mut U, { let pointer = Pin::get_unchecked_mut(self); @@ -787,13 +816,7 @@ impl fmt::Pointer for Pin

{ // for other reasons, though, so we just need to take care not to allow such // impls to land in std. #[stable(feature = "pin", since = "1.33.0")] -impl CoerceUnsized> for Pin

-where - P: CoerceUnsized, -{} +impl CoerceUnsized> for Pin

where P: CoerceUnsized {} #[stable(feature = "pin", since = "1.33.0")] -impl DispatchFromDyn> for Pin

-where - P: DispatchFromDyn, -{} +impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 7cc279a9ef..66b5a90b77 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -25,25 +25,25 @@ pub use crate::mem::drop; pub use crate::clone::Clone; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord}; +pub use crate::cmp::{Eq, Ord, PartialEq, PartialOrd}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use crate::convert::{AsRef, AsMut, Into, From}; +pub use crate::convert::{AsMut, AsRef, From, Into}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::default::Default; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use crate::iter::{Iterator, Extend, IntoIterator}; +pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator}; +pub use crate::iter::{Extend, IntoIterator, Iterator}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use crate::option::Option::{self, Some, None}; +pub use crate::option::Option::{self, None, Some}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use crate::result::Result::{self, Ok, Err}; +pub use crate::result::Result::{self, Err, Ok}; // Re-exported built-in macros #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] @@ -56,37 +56,14 @@ pub use crate::hash::macros::Hash; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::{ - asm, - assert, - cfg, - column, - compile_error, - concat, - concat_idents, - env, - file, - format_args, - format_args_nl, - global_asm, - include, - include_bytes, - include_str, - line, - log_syntax, - module_path, - option_env, - stringify, - trace_macros, + asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, + format_args_nl, global_asm, include, include_bytes, include_str, line, log_syntax, module_path, + option_env, stringify, trace_macros, }; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(no_inline)] pub use crate::macros::builtin::{ - RustcDecodable, - RustcEncodable, - bench, - global_allocator, - test, - test_case, + bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 1355ce1aa4..33c23233fd 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -18,6 +18,10 @@ //! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst]. //! * All pointers (except for the null pointer) are valid for all operations of //! [size zero][zst]. +//! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer +//! be *dereferencable*: the memory range of the given size starting at the pointer must all be +//! within the bounds of a single allocated object. Note that in Rust, +//! every (stack-allocated) variable is considered a separate allocated object. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different @@ -61,13 +65,16 @@ //! [`write_volatile`]: ./fn.write_volatile.html //! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling +// ignore-tidy-filelength +// ignore-tidy-undocumented-unsafe + #![stable(feature = "rust1", since = "1.0.0")] -use crate::intrinsics; +use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::fmt; use crate::hash; +use crate::intrinsics; use crate::mem::{self, MaybeUninit}; -use crate::cmp::Ordering::{self, Less, Equal, Greater}; #[stable(feature = "rust1", since = "1.0.0")] pub use crate::intrinsics::copy_nonoverlapping; @@ -191,7 +198,10 @@ unsafe fn real_drop_in_place(to_drop: &mut T) { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -pub const fn null() -> *const T { 0 as *const T } +#[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_ptr_null", since = "1.32.0"))] +pub const fn null() -> *const T { + 0 as *const T +} /// Creates a null mutable raw pointer. /// @@ -206,7 +216,10 @@ pub const fn null() -> *const T { 0 as *const T } #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -pub const fn null_mut() -> *mut T { 0 as *mut T } +#[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_ptr_null", since = "1.32.0"))] +pub const fn null_mut() -> *mut T { + 0 as *mut T +} #[repr(C)] pub(crate) union Repr { @@ -221,10 +234,15 @@ pub(crate) struct FatPtr { pub(crate) len: usize, } -/// Forms a slice from a pointer and a length. +/// Forms a raw slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes. /// +/// This function is safe, but actually using the return value is unsafe. +/// See the documentation of [`from_raw_parts`] for slice safety requirements. +/// +/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html +/// /// # Examples /// /// ```rust @@ -243,12 +261,16 @@ pub fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { unsafe { Repr { raw: FatPtr { data, len } }.rust } } -/// Performs the same functionality as [`from_raw_parts`], except that a -/// mutable slice is returned. +/// Performs the same functionality as [`slice_from_raw_parts`], except that a +/// raw mutable slice is returned, as opposed to a raw immutable slice. /// -/// See the documentation of [`from_raw_parts`] for more details. +/// See the documentation of [`slice_from_raw_parts`] for more details. /// -/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html +/// This function is safe, but actually using the return value is unsafe. +/// See the documentation of [`from_raw_parts_mut`] for slice safety requirements. +/// +/// [`slice_from_raw_parts`]: fn.slice_from_raw_parts.html +/// [`from_raw_parts_mut`]: ../../std/slice/fn.from_raw_parts_mut.html #[inline] #[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")] pub fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { @@ -689,9 +711,7 @@ pub unsafe fn read(src: *const T) -> T { #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn read_unaligned(src: *const T) -> T { let mut tmp = MaybeUninit::::uninit(); - copy_nonoverlapping(src as *const u8, - tmp.as_mut_ptr() as *mut u8, - mem::size_of::()); + copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::()); tmp.assume_init() } @@ -874,9 +894,7 @@ pub unsafe fn write(dst: *mut T, src: T) { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn write_unaligned(dst: *mut T, src: T) { - copy_nonoverlapping(&src as *const T as *const u8, - dst as *mut u8, - mem::size_of::()); + copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::()); mem::forget(src); } @@ -1044,6 +1062,7 @@ impl *const T { /// Casts to a pointer of another type. #[stable(feature = "ptr_cast", since = "1.38.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0"))] #[inline] pub const fn cast(self) -> *const U { self as _ @@ -1059,17 +1078,22 @@ impl *const T { /// operation because the returned value could be pointing to invalid /// memory. /// - /// When calling this method, you have to ensure that if the pointer is - /// non-NULL, then it is properly aligned, dereferencable (for the whole - /// size of `T`) and points to an initialized instance of `T`. This applies - /// even if the result of this method is unused! + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// - it is properly aligned + /// - it must point to an initialized instance of T; in particular, the pointer must be + /// "dereferencable" in the sense defined [here]. + /// + /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is, the only safe approach is to ensure that they are indeed initialized.) /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. It is up to the - /// caller to ensure that for the duration of this lifetime, the memory this - /// pointer points to does not get written to outside of `UnsafeCell`. + /// not necessarily reflect the actual lifetime of the data. *You* must enforce + /// Rust's aliasing rules. In particular, for the duration of this lifetime, + /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`). + /// + /// [here]: crate::ptr#safety /// /// # Examples /// @@ -1102,11 +1126,7 @@ impl *const T { #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { - if self.is_null() { - None - } else { - Some(&*self) - } + if self.is_null() { None } else { Some(&*self) } } /// Calculates the offset from a pointer. @@ -1162,7 +1182,10 @@ impl *const T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub unsafe fn offset(self, count: isize) -> *const T where T: Sized { + pub unsafe fn offset(self, count: isize) -> *const T + where + T: Sized, + { intrinsics::offset(self, count) } @@ -1217,10 +1240,11 @@ impl *const T { /// ``` #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[inline] - pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized { - unsafe { - intrinsics::arith_offset(self, count) - } + pub fn wrapping_offset(self, count: isize) -> *const T + where + T: Sized, + { + unsafe { intrinsics::arith_offset(self, count) } } /// Calculates the distance between two pointers. The returned value is in @@ -1286,10 +1310,16 @@ impl *const T { /// } /// ``` #[unstable(feature = "ptr_offset_from", issue = "41079")] - #[cfg(not(bootstrap))] - #[rustc_const_unstable(feature = "const_ptr_offset_from")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ptr_offset_from"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079"), + )] #[inline] - pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { + pub const unsafe fn offset_from(self, origin: *const T) -> isize + where + T: Sized, + { let pointee_size = mem::size_of::(); let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize; // assert that the pointee size is valid in a const eval compatible way @@ -1298,21 +1328,6 @@ impl *const T { intrinsics::ptr_offset_from(self, origin) } - #[unstable(feature = "ptr_offset_from", issue = "41079")] - #[inline] - #[cfg(bootstrap)] - /// bootstrap - pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { - let pointee_size = mem::size_of::(); - assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize); - - // This is the same sequence that Clang emits for pointer subtraction. - // It can be neither `nsw` nor `nuw` because the input is treated as - // unsigned but then the output is treated as signed, so neither works. - let d = isize::wrapping_sub(self as _, origin as _); - intrinsics::exact_div(d, pointee_size as _) - } - /// Calculates the distance between two pointers. The returned value is in /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// @@ -1349,7 +1364,10 @@ impl *const T { /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] #[inline] - pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized { + pub fn wrapping_offset_from(self, origin: *const T) -> isize + where + T: Sized, + { let pointee_size = mem::size_of::(); assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize); @@ -1411,7 +1429,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn add(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.offset(count as isize) } @@ -1471,7 +1490,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn sub(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.offset((count as isize).wrapping_neg()) } @@ -1525,7 +1545,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub fn wrapping_add(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.wrapping_offset(count as isize) } @@ -1579,7 +1600,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub fn wrapping_sub(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.wrapping_offset((count as isize).wrapping_neg()) } @@ -1593,7 +1615,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read(self) -> T - where T: Sized, + where + T: Sized, { read(self) } @@ -1611,7 +1634,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_volatile(self) -> T - where T: Sized, + where + T: Sized, { read_volatile(self) } @@ -1627,7 +1651,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_unaligned(self) -> T - where T: Sized, + where + T: Sized, { read_unaligned(self) } @@ -1643,7 +1668,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to(self, dest: *mut T, count: usize) - where T: Sized, + where + T: Sized, { copy(self, dest, count) } @@ -1659,7 +1685,8 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) - where T: Sized, + where + T: Sized, { copy_nonoverlapping(self, dest, count) } @@ -1704,17 +1731,17 @@ impl *const T { /// # } } /// ``` #[stable(feature = "align_offset", since = "1.36.0")] - pub fn align_offset(self, align: usize) -> usize where T: Sized { + pub fn align_offset(self, align: usize) -> usize + where + T: Sized, + { if !align.is_power_of_two() { panic!("align_offset: align is not a power-of-two"); } - unsafe { - align_offset(self, align) - } + unsafe { align_offset(self, align) } } } - #[lang = "mut_ptr"] impl *mut T { /// Returns `true` if the pointer is null. @@ -1743,6 +1770,7 @@ impl *mut T { /// Casts to a pointer of another type. #[stable(feature = "ptr_cast", since = "1.38.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0"))] #[inline] pub const fn cast(self) -> *mut U { self as _ @@ -1801,11 +1829,7 @@ impl *mut T { #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { - if self.is_null() { - None - } else { - Some(&*self) - } + if self.is_null() { None } else { Some(&*self) } } /// Calculates the offset from a pointer. @@ -1861,7 +1885,10 @@ impl *mut T { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub unsafe fn offset(self, count: isize) -> *mut T where T: Sized { + pub unsafe fn offset(self, count: isize) -> *mut T + where + T: Sized, + { intrinsics::offset(self, count) as *mut T } @@ -1915,10 +1942,11 @@ impl *mut T { /// ``` #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")] #[inline] - pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized { - unsafe { - intrinsics::arith_offset(self, count) as *mut T - } + pub fn wrapping_offset(self, count: isize) -> *mut T + where + T: Sized, + { + unsafe { intrinsics::arith_offset(self, count) as *mut T } } /// Returns `None` if the pointer is null, or else returns a mutable @@ -1930,18 +1958,23 @@ impl *mut T { /// of the returned pointer, nor can it ensure that the lifetime `'a` /// returned is indeed a valid lifetime for the contained data. /// - /// When calling this method, you have to ensure that if the pointer is - /// non-NULL, then it is properly aligned, dereferencable (for the whole - /// size of `T`) and points to an initialized instance of `T`. This applies - /// even if the result of this method is unused! + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// - it is properly aligned + /// - it must point to an initialized instance of T; in particular, the pointer must be + /// "dereferencable" in the sense defined [here]. + /// + /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is the only safe approach is to ensure that they are indeed initialized.) /// /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. It is up to the - /// caller to ensure that for the duration of this lifetime, the memory this - /// pointer points to does not get accessed through any other pointer. + /// not necessarily reflect the actual lifetime of the data. *You* must enforce + /// Rust's aliasing rules. In particular, for the duration of this lifetime, + /// the memory this pointer points to must not get accessed (read or written) + /// through any other pointer. /// + /// [here]: crate::ptr#safety /// [`as_ref`]: #method.as_ref /// /// # Examples @@ -1958,11 +1991,7 @@ impl *mut T { #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[inline] pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { - if self.is_null() { - None - } else { - Some(&mut *self) - } + if self.is_null() { None } else { Some(&mut *self) } } /// Calculates the distance between two pointers. The returned value is in @@ -2028,9 +2057,16 @@ impl *mut T { /// } /// ``` #[unstable(feature = "ptr_offset_from", issue = "41079")] - #[rustc_const_unstable(feature = "const_ptr_offset_from")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ptr_offset_from"))] + #[cfg_attr( + not(bootstrap), + rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079"), + )] #[inline] - pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { + pub const unsafe fn offset_from(self, origin: *const T) -> isize + where + T: Sized, + { (self as *const T).offset_from(origin) } @@ -2070,7 +2106,10 @@ impl *mut T { /// ``` #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")] #[inline] - pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized { + pub fn wrapping_offset_from(self, origin: *const T) -> isize + where + T: Sized, + { (self as *const T).wrapping_offset_from(origin) } @@ -2128,7 +2167,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn add(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.offset(count as isize) } @@ -2188,7 +2228,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn sub(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.offset((count as isize).wrapping_neg()) } @@ -2242,7 +2283,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub fn wrapping_add(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.wrapping_offset(count as isize) } @@ -2296,7 +2338,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub fn wrapping_sub(self, count: usize) -> Self - where T: Sized, + where + T: Sized, { self.wrapping_offset((count as isize).wrapping_neg()) } @@ -2310,7 +2353,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read(self) -> T - where T: Sized, + where + T: Sized, { read(self) } @@ -2328,7 +2372,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_volatile(self) -> T - where T: Sized, + where + T: Sized, { read_volatile(self) } @@ -2344,7 +2389,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn read_unaligned(self) -> T - where T: Sized, + where + T: Sized, { read_unaligned(self) } @@ -2360,7 +2406,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to(self, dest: *mut T, count: usize) - where T: Sized, + where + T: Sized, { copy(self, dest, count) } @@ -2376,7 +2423,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize) - where T: Sized, + where + T: Sized, { copy_nonoverlapping(self, dest, count) } @@ -2392,7 +2440,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_from(self, src: *const T, count: usize) - where T: Sized, + where + T: Sized, { copy(src, self, count) } @@ -2408,7 +2457,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize) - where T: Sized, + where + T: Sized, { copy_nonoverlapping(src, self, count) } @@ -2433,7 +2483,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write(self, val: T) - where T: Sized, + where + T: Sized, { write(self, val) } @@ -2447,7 +2498,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write_bytes(self, val: u8, count: usize) - where T: Sized, + where + T: Sized, { write_bytes(self, val, count) } @@ -2465,7 +2517,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write_volatile(self, val: T) - where T: Sized, + where + T: Sized, { write_volatile(self, val) } @@ -2481,7 +2534,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn write_unaligned(self, val: T) - where T: Sized, + where + T: Sized, { write_unaligned(self, val) } @@ -2495,7 +2549,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn replace(self, src: T) -> T - where T: Sized, + where + T: Sized, { replace(self, src) } @@ -2510,7 +2565,8 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] pub unsafe fn swap(self, with: *mut T) - where T: Sized, + where + T: Sized, { swap(self, with) } @@ -2555,13 +2611,14 @@ impl *mut T { /// # } } /// ``` #[stable(feature = "align_offset", since = "1.36.0")] - pub fn align_offset(self, align: usize) -> usize where T: Sized { + pub fn align_offset(self, align: usize) -> usize + where + T: Sized, + { if !align.is_power_of_two() { panic!("align_offset: align is not a power-of-two"); } - unsafe { - align_offset(self, align) - } + unsafe { align_offset(self, align) } } } @@ -2579,7 +2636,7 @@ impl *mut T { /// than trying to adapt this to accommodate that change. /// /// Any questions go to @nagisa. -#[lang="align_offset"] +#[lang = "align_offset"] pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { /// Calculate multiplicative modular inverse of `x` modulo `m`. /// @@ -2619,9 +2676,8 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { // uses e.g., subtraction `mod n`. It is entirely fine to do them `mod // usize::max_value()` instead, because we take the result `mod n` at the end // anyway. - inverse = inverse.wrapping_mul( - 2usize.wrapping_sub(x.wrapping_mul(inverse)) - ) & (going_mod - 1); + inverse = inverse.wrapping_mul(2usize.wrapping_sub(x.wrapping_mul(inverse))) + & (going_mod - 1); if going_mod > m { return inverse & (m - 1); } @@ -2680,13 +2736,13 @@ pub(crate) unsafe fn align_offset(p: *const T, a: usize) -> usize { usize::max_value() } - - // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for *const T { #[inline] - fn eq(&self, other: &*const T) -> bool { *self == *other } + fn eq(&self, other: &*const T) -> bool { + *self == *other + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2695,7 +2751,9 @@ impl Eq for *const T {} #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for *mut T { #[inline] - fn eq(&self, other: &*mut T) -> bool { *self == *other } + fn eq(&self, other: &*mut T) -> bool { + *self == *other + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2881,7 +2939,7 @@ macro_rules! fnptr_impls_args { }; } -fnptr_impls_args! { } +fnptr_impls_args! {} fnptr_impls_args! { A } fnptr_impls_args! { A, B } fnptr_impls_args! { A, B, C } @@ -2918,16 +2976,24 @@ impl PartialOrd for *const T { } #[inline] - fn lt(&self, other: &*const T) -> bool { *self < *other } + fn lt(&self, other: &*const T) -> bool { + *self < *other + } #[inline] - fn le(&self, other: &*const T) -> bool { *self <= *other } + fn le(&self, other: &*const T) -> bool { + *self <= *other + } #[inline] - fn gt(&self, other: &*const T) -> bool { *self > *other } + fn gt(&self, other: &*const T) -> bool { + *self > *other + } #[inline] - fn ge(&self, other: &*const T) -> bool { *self >= *other } + fn ge(&self, other: &*const T) -> bool { + *self >= *other + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2952,14 +3018,22 @@ impl PartialOrd for *mut T { } #[inline] - fn lt(&self, other: &*mut T) -> bool { *self < *other } + fn lt(&self, other: &*mut T) -> bool { + *self < *other + } #[inline] - fn le(&self, other: &*mut T) -> bool { *self <= *other } + fn le(&self, other: &*mut T) -> bool { + *self <= *other + } #[inline] - fn gt(&self, other: &*mut T) -> bool { *self > *other } + fn gt(&self, other: &*mut T) -> bool { + *self > *other + } #[inline] - fn ge(&self, other: &*mut T) -> bool { *self >= *other } + fn ge(&self, other: &*mut T) -> bool { + *self >= *other + } } diff --git a/src/libcore/ptr/non_null.rs b/src/libcore/ptr/non_null.rs index 7dcd57f1f9..d1d97d7b33 100644 --- a/src/libcore/ptr/non_null.rs +++ b/src/libcore/ptr/non_null.rs @@ -1,11 +1,13 @@ +use crate::cmp::Ordering; use crate::convert::From; -use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::fmt; use crate::hash; use crate::marker::Unsize; use crate::mem; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::ptr::Unique; -use crate::cmp::Ordering; + +// ignore-tidy-undocumented-unsafe /// `*mut T` but non-zero and covariant. /// @@ -46,12 +48,12 @@ pub struct NonNull { /// `NonNull` pointers are not `Send` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Send for NonNull { } +impl !Send for NonNull {} /// `NonNull` pointers are not `Sync` because the data they reference may be aliased. // N.B., this impl is unnecessary, but should provide better error messages. #[stable(feature = "nonnull", since = "1.25.0")] -impl !Sync for NonNull { } +impl !Sync for NonNull {} impl NonNull { /// Creates a new `NonNull` that is dangling, but well-aligned. @@ -64,6 +66,10 @@ impl NonNull { /// sentinel value. Types that lazily allocate must track initialization by /// some other means. #[stable(feature = "nonnull", since = "1.25.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_nonnull_dangling", since = "1.32.0"), + )] #[inline] pub const fn dangling() -> Self { unsafe { @@ -80,6 +86,10 @@ impl NonNull { /// /// `ptr` must be non-null. #[stable(feature = "nonnull", since = "1.25.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.32.0"), + )] #[inline] pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { NonNull { pointer: ptr as _ } @@ -89,15 +99,15 @@ impl NonNull { #[stable(feature = "nonnull", since = "1.25.0")] #[inline] pub fn new(ptr: *mut T) -> Option { - if !ptr.is_null() { - Some(unsafe { Self::new_unchecked(ptr) }) - } else { - None - } + if !ptr.is_null() { Some(unsafe { Self::new_unchecked(ptr) }) } else { None } } /// Acquires the underlying `*mut` pointer. #[stable(feature = "nonnull", since = "1.25.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0"), + )] #[inline] pub const fn as_ptr(self) -> *mut T { self.pointer as *mut T @@ -127,11 +137,13 @@ impl NonNull { /// Casts to a pointer of another type. #[stable(feature = "nonnull_cast", since = "1.27.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_nonnull_cast", since = "1.32.0"), + )] #[inline] pub const fn cast(self) -> NonNull { - unsafe { - NonNull::new_unchecked(self.as_ptr() as *mut U) - } + unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } } } @@ -144,13 +156,13 @@ impl Clone for NonNull { } #[stable(feature = "nonnull", since = "1.25.0")] -impl Copy for NonNull { } +impl Copy for NonNull {} #[unstable(feature = "coerce_unsized", issue = "27732")] -impl CoerceUnsized> for NonNull where T: Unsize { } +impl CoerceUnsized> for NonNull where T: Unsize {} #[unstable(feature = "dispatch_from_dyn", issue = "0")] -impl DispatchFromDyn> for NonNull where T: Unsize { } +impl DispatchFromDyn> for NonNull where T: Unsize {} #[stable(feature = "nonnull", since = "1.25.0")] impl fmt::Debug for NonNull { diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index 3521dd7997..546b7c9d77 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -1,10 +1,12 @@ use crate::convert::From; -use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::fmt; use crate::marker::{PhantomData, Unsize}; use crate::mem; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::ptr::NonNull; +// ignore-tidy-undocumented-unsafe + /// A wrapper around a raw non-null `*mut T` that indicates that the possessor /// of this wrapper owns the referent. Useful for building abstractions like /// `Box`, `Vec`, `String`, and `HashMap`. @@ -25,9 +27,12 @@ use crate::ptr::NonNull; /// /// Unlike `*mut T`, `Unique` is covariant over `T`. This should always be correct /// for any type which upholds Unique's aliasing requirements. -#[unstable(feature = "ptr_internals", issue = "0", - reason = "use `NonNull` instead and consider `PhantomData` \ - (if you also use `#[may_dangle]`), `Send`, and/or `Sync`")] +#[unstable( + feature = "ptr_internals", + issue = "0", + reason = "use `NonNull` instead and consider `PhantomData` \ + (if you also use `#[may_dangle]`), `Send`, and/or `Sync`" +)] #[doc(hidden)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -46,14 +51,14 @@ pub struct Unique { /// unenforced by the type system; the abstraction using the /// `Unique` must enforce it. #[unstable(feature = "ptr_internals", issue = "0")] -unsafe impl Send for Unique { } +unsafe impl Send for Unique {} /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they /// reference is unaliased. Note that this aliasing invariant is /// unenforced by the type system; the abstraction using the /// `Unique` must enforce it. #[unstable(feature = "ptr_internals", issue = "0")] -unsafe impl Sync for Unique { } +unsafe impl Sync for Unique {} #[unstable(feature = "ptr_internals", issue = "0")] impl Unique { @@ -69,9 +74,7 @@ impl Unique { // FIXME: rename to dangling() to match NonNull? #[inline] pub const fn empty() -> Self { - unsafe { - Unique::new_unchecked(mem::align_of::() as *mut T) - } + unsafe { Unique::new_unchecked(mem::align_of::() as *mut T) } } } @@ -126,9 +129,7 @@ impl Unique { /// Casts to a pointer of another type. #[inline] pub const fn cast(self) -> Unique { - unsafe { - Unique::new_unchecked(self.as_ptr() as *mut U) - } + unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) } } } @@ -141,13 +142,13 @@ impl Clone for Unique { } #[unstable(feature = "ptr_internals", issue = "0")] -impl Copy for Unique { } +impl Copy for Unique {} #[unstable(feature = "ptr_internals", issue = "0")] -impl CoerceUnsized> for Unique where T: Unsize { } +impl CoerceUnsized> for Unique where T: Unsize {} #[unstable(feature = "ptr_internals", issue = "0")] -impl DispatchFromDyn> for Unique where T: Unsize { } +impl DispatchFromDyn> for Unique where T: Unsize {} #[unstable(feature = "ptr_internals", issue = "0")] impl fmt::Debug for Unique { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index ed40a5f31d..fb4dc62d8c 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -514,6 +514,27 @@ impl Result { } } + /// Applies a function to the contained value (if any), + /// or returns the provided default (if not). + /// + /// # Examples + /// + /// ``` + /// let x: Result<_, &str> = Ok("foo"); + /// assert_eq!(x.map_or(42, |v| v.len()), 3); + /// + /// let x: Result<&str, _> = Err("bar"); + /// assert_eq!(x.map_or(42, |v| v.len()), 42); + /// ``` + #[inline] + #[stable(feature = "result_map_or", since = "1.41.0")] + pub fn map_or U>(self, default: U, f: F) -> U { + match self { + Ok(t) => f(t), + Err(_) => default, + } + } + /// Maps a `Result` to `U` by applying a function to a /// contained [`Ok`] value, or a fallback function to a /// contained [`Err`] value. @@ -529,7 +550,6 @@ impl Result { /// Basic usage: /// /// ``` - /// #![feature(result_map_or_else)] /// let k = 21; /// /// let x : Result<_, &str> = Ok("foo"); @@ -539,9 +559,12 @@ impl Result { /// assert_eq!(x.map_or_else(|e| k * 2, |v| v.len()), 42); /// ``` #[inline] - #[unstable(feature = "result_map_or_else", issue = "53268")] - pub fn map_or_else U, F: FnOnce(E) -> U>(self, fallback: F, map: M) -> U { - self.map(map).unwrap_or_else(fallback) + #[stable(feature = "result_map_or_else", since = "1.41.0")] + pub fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + match self { + Ok(t) => f(t), + Err(e) => default(e), + } } /// Maps a `Result` to `Result` by applying a function to a diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs index 45ab016c49..2a2169dd34 100644 --- a/src/libcore/slice/memchr.rs +++ b/src/libcore/slice/memchr.rs @@ -1,6 +1,8 @@ // Original implementation taken from rust-memchr. // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch +// ignore-tidy-undocumented-unsafe + use crate::cmp; use crate::mem; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index cdada1252d..a8e500d256 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1,4 +1,5 @@ // ignore-tidy-filelength +// ignore-tidy-undocumented-unsafe //! Slice management and manipulation. //! @@ -61,6 +62,7 @@ impl [T] { /// assert_eq!(a.len(), 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_slice_len", since = "1.32.0"))] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) #[allow(unused_attributes)] @@ -80,6 +82,10 @@ impl [T] { /// assert!(!a.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_slice_is_empty", since = "1.32.0"), + )] #[inline] pub const fn is_empty(&self) -> bool { self.len() == 0 @@ -375,6 +381,10 @@ impl [T] { /// /// [`as_mut_ptr`]: #method.as_mut_ptr #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0"), + )] #[inline] pub const fn as_ptr(&self) -> *const T { self as *const [T] as *const T @@ -5272,18 +5282,24 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { /// /// # Safety /// -/// This function is unsafe as there is no guarantee that the given pointer is -/// valid for `len` elements, nor whether the lifetime inferred is a suitable -/// lifetime for the returned slice. +/// Behavior is undefined if any of the following conditions are violated: /// -/// `data` must be non-null and aligned, even for zero-length slices. One -/// reason for this is that enum layout optimizations may rely on references -/// (including slices of any length) being aligned and non-null to distinguish -/// them from other data. You can obtain a pointer that is usable as `data` -/// for zero-length slices using [`NonNull::dangling()`]. +/// * `data` must be [valid] for reads for `len * mem::size_of::()` many bytes, +/// and it must be properly aligned. This means in particular: /// -/// The total size of the slice must be no larger than `isize::MAX` **bytes** -/// in memory. See the safety documentation of [`pointer::offset`]. +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. +/// * `data` must be non-null and aligned even for zero-length slices. One +/// reason for this is that enum layout optimizations may rely on references +/// (including slices of any length) being aligned and non-null to distinguish +/// them from other data. You can obtain a pointer that is usable as `data` +/// for zero-length slices using [`NonNull::dangling()`]. +/// +/// * The memory referenced by the returned slice must not be mutated for the duration +/// of lifetime `'a`, except inside an `UnsafeCell`. +/// +/// * The total size `len * mem::size_of::()` of the slice must be no larger than `isize::MAX`. +/// See the safety documentation of [`pointer::offset`]. /// /// # Caveat /// @@ -5305,6 +5321,7 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { /// assert_eq!(slice[0], 42); /// ``` /// +/// [valid]: ../../std/ptr/index.html#safety /// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] @@ -5312,28 +5329,45 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, - "attempt to create slice covering half the address space"); + "attempt to create slice covering at least half the address space"); &*ptr::slice_from_raw_parts(data, len) } /// Performs the same functionality as [`from_raw_parts`], except that a /// mutable slice is returned. /// -/// This function is unsafe for the same reasons as [`from_raw_parts`], as well -/// as not being able to provide a non-aliasing guarantee of the returned -/// mutable slice. `data` must be non-null and aligned even for zero-length -/// slices as with [`from_raw_parts`]. The total size of the slice must be no -/// larger than `isize::MAX` **bytes** in memory. +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `data` must be [valid] for writes for `len * mem::size_of::()` many bytes, +/// and it must be properly aligned. This means in particular: /// -/// See the documentation of [`from_raw_parts`] for more details. +/// * The entire memory range of this slice must be contained within a single allocated object! +/// Slices can never span across multiple allocated objects. +/// * `data` must be non-null and aligned even for zero-length slices. One +/// reason for this is that enum layout optimizations may rely on references +/// (including slices of any length) being aligned and non-null to distinguish +/// them from other data. You can obtain a pointer that is usable as `data` +/// for zero-length slices using [`NonNull::dangling()`]. /// +/// * The memory referenced by the returned slice must not be accessed through any other pointer +/// (not derived from the return value) for the duration of lifetime `'a`. +/// Both read and write accesses are forbidden. +/// +/// * The total size `len * mem::size_of::()` of the slice must be no larger than `isize::MAX`. +/// See the safety documentation of [`pointer::offset`]. +/// +/// [valid]: ../../std/ptr/index.html#safety +/// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling +/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset /// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, - "attempt to create slice covering half the address space"); + "attempt to create slice covering at least half the address space"); &mut *ptr::slice_from_raw_parts_mut(data, len) } diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 2f2170f7ff..019832e16f 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -6,6 +6,8 @@ //! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our //! stable sorting implementation. +// ignore-tidy-undocumented-unsafe + use crate::cmp; use crate::mem::{self, MaybeUninit}; use crate::ptr; @@ -18,13 +20,16 @@ struct CopyOnDrop { impl Drop for CopyOnDrop { fn drop(&mut self) { - unsafe { ptr::copy_nonoverlapping(self.src, self.dest, 1); } + unsafe { + ptr::copy_nonoverlapping(self.src, self.dest, 1); + } } } /// Shifts the first element to the right until it encounters a greater or equal element. fn shift_head(v: &mut [T], is_less: &mut F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { let len = v.len(); unsafe { @@ -34,10 +39,7 @@ fn shift_head(v: &mut [T], is_less: &mut F) // operation panics, `hole` will get dropped and automatically write the element back // into the slice. let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0))); - let mut hole = CopyOnDrop { - src: &mut *tmp, - dest: v.get_unchecked_mut(1), - }; + let mut hole = CopyOnDrop { src: &mut *tmp, dest: v.get_unchecked_mut(1) }; ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1); for i in 2..len { @@ -56,7 +58,8 @@ fn shift_head(v: &mut [T], is_less: &mut F) /// Shifts the last element to the left until it encounters a smaller or equal element. fn shift_tail(v: &mut [T], is_less: &mut F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { let len = v.len(); unsafe { @@ -66,13 +69,10 @@ fn shift_tail(v: &mut [T], is_less: &mut F) // operation panics, `hole` will get dropped and automatically write the element back // into the slice. let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1))); - let mut hole = CopyOnDrop { - src: &mut *tmp, - dest: v.get_unchecked_mut(len - 2), - }; + let mut hole = CopyOnDrop { src: &mut *tmp, dest: v.get_unchecked_mut(len - 2) }; ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1); - for i in (0..len-2).rev() { + for i in (0..len - 2).rev() { if !is_less(&*tmp, v.get_unchecked(i)) { break; } @@ -91,7 +91,8 @@ fn shift_tail(v: &mut [T], is_less: &mut F) /// Returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case. #[cold] fn partial_insertion_sort(v: &mut [T], is_less: &mut F) -> bool - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // Maximum number of adjacent out-of-order pairs that will get shifted. const MAX_STEPS: usize = 5; @@ -134,17 +135,19 @@ fn partial_insertion_sort(v: &mut [T], is_less: &mut F) -> bool /// Sorts a slice using insertion sort, which is `O(n^2)` worst-case. fn insertion_sort(v: &mut [T], is_less: &mut F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { for i in 1..v.len() { - shift_tail(&mut v[..i+1], is_less); + shift_tail(&mut v[..i + 1], is_less); } } /// Sorts `v` using heapsort, which guarantees `O(n log n)` worst-case. #[cold] pub fn heapsort(v: &mut [T], is_less: &mut F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // This binary heap respects the invariant `parent >= child`. let mut sift_down = |v: &mut [T], mut node| { @@ -154,11 +157,8 @@ pub fn heapsort(v: &mut [T], is_less: &mut F) let right = 2 * node + 2; // Choose the greater child. - let greater = if right < v.len() && is_less(&v[left], &v[right]) { - right - } else { - left - }; + let greater = + if right < v.len() && is_less(&v[left], &v[right]) { right } else { left }; // Stop if the invariant holds at `node`. if greater >= v.len() || !is_less(&v[node], &v[greater]) { @@ -172,12 +172,12 @@ pub fn heapsort(v: &mut [T], is_less: &mut F) }; // Build the heap in linear time. - for i in (0 .. v.len() / 2).rev() { + for i in (0..v.len() / 2).rev() { sift_down(v, i); } // Pop maximal elements from the heap. - for i in (1 .. v.len()).rev() { + for i in (1..v.len()).rev() { v.swap(0, i); sift_down(&mut v[..i], 0); } @@ -193,7 +193,8 @@ pub fn heapsort(v: &mut [T], is_less: &mut F) /// /// [pdf]: http://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // Number of elements in a typical block. const BLOCK: usize = 128; @@ -296,8 +297,16 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize let count = cmp::min(width(start_l, end_l), width(start_r, end_r)); if count > 0 { - macro_rules! left { () => { l.offset(*start_l as isize) } } - macro_rules! right { () => { r.offset(-(*start_r as isize) - 1) } } + macro_rules! left { + () => { + l.offset(*start_l as isize) + }; + } + macro_rules! right { + () => { + r.offset(-(*start_r as isize) - 1) + }; + } // Instead of swapping one pair at the time, it is more efficient to perform a cyclic // permutation. This is not strictly equivalent to swapping, but produces a similar @@ -377,7 +386,8 @@ fn partition_in_blocks(v: &mut [T], pivot: &T, is_less: &mut F) -> usize /// 1. Number of elements smaller than `v[pivot]`. /// 2. True if `v` was already partitioned. fn partition(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { let (mid, was_partitioned) = { // Place the pivot at the beginning of slice. @@ -388,10 +398,7 @@ fn partition(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool) // Read the pivot into a stack-allocated variable for efficiency. If a following comparison // operation panics, the pivot will be automatically written back into the slice. let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); - let _pivot_guard = CopyOnDrop { - src: &mut *tmp, - dest: pivot, - }; + let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot }; let pivot = &*tmp; // Find the first pair of out-of-order elements. @@ -427,7 +434,8 @@ fn partition(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool) /// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain /// elements smaller than the pivot. fn partition_equal(v: &mut [T], pivot: usize, is_less: &mut F) -> usize - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // Place the pivot at the beginning of slice. v.swap(0, pivot); @@ -437,10 +445,7 @@ fn partition_equal(v: &mut [T], pivot: usize, is_less: &mut F) -> usize // Read the pivot into a stack-allocated variable for efficiency. If a following comparison // operation panics, the pivot will be automatically written back into the slice. let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); - let _pivot_guard = CopyOnDrop { - src: &mut *tmp, - dest: pivot, - }; + let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot }; let pivot = &*tmp; // Now partition the slice. @@ -526,7 +531,8 @@ fn break_patterns(v: &mut [T]) { /// /// Elements in `v` might be reordered in the process. fn choose_pivot(v: &mut [T], is_less: &mut F) -> (usize, bool) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // Minimum length to choose the median-of-medians method. // Shorter slices use the simple median-of-three method. @@ -594,7 +600,8 @@ fn choose_pivot(v: &mut [T], is_less: &mut F) -> (usize, bool) /// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero, /// this function will immediately switch to heapsort. fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: usize) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // Slices of up to this length get sorted using insertion sort. const MAX_INSERTION: usize = 20; @@ -648,7 +655,7 @@ fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T let mid = partition_equal(v, pivot, is_less); // Continue sorting elements greater than the pivot. - v = &mut {v}[mid..]; + v = &mut { v }[mid..]; continue; } } @@ -659,7 +666,7 @@ fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T was_partitioned = was_p; // Split the slice into `left`, `pivot`, and `right`. - let (left, right) = {v}.split_at_mut(mid); + let (left, right) = { v }.split_at_mut(mid); let (pivot, right) = right.split_at_mut(1); let pivot = &pivot[0]; @@ -679,7 +686,8 @@ fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T /// Sorts `v` using pattern-defeating quicksort, which is `O(n log n)` worst-case. pub fn quicksort(v: &mut [T], mut is_less: F) - where F: FnMut(&T, &T) -> bool +where + F: FnMut(&T, &T) -> bool, { // Sorting has no meaningful behavior on zero-sized types. if mem::size_of::() == 0 { @@ -692,8 +700,13 @@ pub fn quicksort(v: &mut [T], mut is_less: F) recurse(v, &mut is_less, None, limit); } -fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, is_less: &mut F - , mut pred: Option<&'a T>) where F: FnMut(&T, &T) -> bool +fn partition_at_index_loop<'a, T, F>( + mut v: &'a mut [T], + mut index: usize, + is_less: &mut F, + mut pred: Option<&'a T>, +) where + F: FnMut(&T, &T) -> bool, { loop { // For slices of up to this length it's probably faster to simply sort them. @@ -729,7 +742,7 @@ fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, is_l let (mid, _) = partition(v, pivot, is_less); // Split the slice into `left`, `pivot`, and `right`. - let (left, right) = {v}.split_at_mut(mid); + let (left, right) = { v }.split_at_mut(mid); let (pivot, right) = right.split_at_mut(1); let pivot = &pivot[0]; @@ -747,11 +760,16 @@ fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, is_l } } -pub fn partition_at_index(v: &mut [T], index: usize, mut is_less: F) - -> (&mut [T], &mut T, &mut [T]) where F: FnMut(&T, &T) -> bool +pub fn partition_at_index( + v: &mut [T], + index: usize, + mut is_less: F, +) -> (&mut [T], &mut T, &mut [T]) +where + F: FnMut(&T, &T) -> bool, { - use cmp::Ordering::Less; use cmp::Ordering::Greater; + use cmp::Ordering::Less; if index >= v.len() { panic!("partition_at_index index {} greater than length of slice {}", index, v.len()); @@ -762,14 +780,20 @@ pub fn partition_at_index(v: &mut [T], index: usize, mut is_less: F) } else if index == v.len() - 1 { // Find max element and place it in the last position of the array. We're free to use // `unwrap()` here because we know v must not be empty. - let (max_index, _) = v.iter().enumerate().max_by( - |&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap(); + let (max_index, _) = v + .iter() + .enumerate() + .max_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }) + .unwrap(); v.swap(max_index, index); } else if index == 0 { // Find min element and place it in the first position of the array. We're free to use // `unwrap()` here because we know v must not be empty. - let (min_index, _) = v.iter().enumerate().min_by( - |&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap(); + let (min_index, _) = v + .iter() + .enumerate() + .min_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }) + .unwrap(); v.swap(min_index, index); } else { partition_at_index_loop(v, index, &mut is_less, None); diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs index e8f747f1a6..762de0489a 100644 --- a/src/libcore/str/lossy.rs +++ b/src/libcore/str/lossy.rs @@ -3,6 +3,8 @@ use crate::str as core_str; use crate::fmt::{self, Write}; use crate::mem; +// ignore-tidy-undocumented-unsafe + /// Lossy UTF-8 string. #[unstable(feature = "str_internals", issue = "0")] pub struct Utf8Lossy { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f67012d8f2..763714e536 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1,4 +1,5 @@ // ignore-tidy-filelength +// ignore-tidy-undocumented-unsafe //! String manipulation. //! @@ -7,7 +8,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use self::pattern::Pattern; -use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; +use self::pattern::{Searcher, SearchStep, ReverseSearcher, DoubleEndedSearcher}; use crate::char; use crate::fmt::{self, Write}; @@ -2085,10 +2086,11 @@ impl str { /// let len = "foo".len(); /// assert_eq!(3, len); /// - /// let len = "ƒoo".len(); // fancy f! - /// assert_eq!(4, len); + /// assert_eq!("ƒoo".len(), 4); // fancy f! + /// assert_eq!("ƒoo".chars().count(), 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_str_len", since = "1.32.0"))] #[inline] pub const fn len(&self) -> usize { self.as_bytes().len() @@ -2109,6 +2111,10 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr( + not(bootstrap), + rustc_const_stable(feature = "const_str_is_empty", since = "1.32.0"), + )] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -2165,6 +2171,7 @@ impl str { /// assert_eq!(b"bors", bytes); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "str_as_bytes", since = "1.32.0"))] #[inline(always)] // SAFETY: const sound because we transmute two types with the same layout #[allow(unused_attributes)] @@ -2238,6 +2245,7 @@ impl str { /// let ptr = s.as_ptr(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0"))] #[inline] pub const fn as_ptr(&self) -> *const u8 { self as *const str as *const u8 @@ -3370,8 +3378,8 @@ impl str { /// An iterator over the disjoint matches of a pattern within the given string /// slice. /// - /// The pattern can be any type that implements the Pattern trait. Notable - /// examples are `&str`, [`char`], and closures that determines the split. + /// The pattern can be a `&str`, [`char`], or a closure that determines if + /// a character matches. /// /// # Iterator behavior /// @@ -3790,6 +3798,77 @@ impl str { } } + /// Returns a string slice with the prefix removed. + /// + /// If the string starts with the pattern `prefix`, `Some` is returned with the substring where + /// the prefix is removed. Unlike `trim_start_matches`, this method removes the prefix exactly + /// once. + /// + /// If the string does not start with `prefix`, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_strip)] + /// + /// assert_eq!("foobar".strip_prefix("foo"), Some("bar")); + /// assert_eq!("foobar".strip_prefix("bar"), None); + /// assert_eq!("foofoo".strip_prefix("foo"), Some("foo")); + /// ``` + #[must_use = "this returns the remaining substring as a new slice, \ + without modifying the original"] + #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")] + pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> { + let mut matcher = prefix.into_searcher(self); + if let SearchStep::Match(start, len) = matcher.next() { + debug_assert_eq!(start, 0, "The first search step from Searcher \ + must include the first character"); + unsafe { + // Searcher is known to return valid indices. + Some(self.get_unchecked(len..)) + } + } else { + None + } + } + + /// Returns a string slice with the suffix removed. + /// + /// If the string ends with the pattern `suffix`, `Some` is returned with the substring where + /// the suffix is removed. Unlike `trim_end_matches`, this method removes the suffix exactly + /// once. + /// + /// If the string does not end with `suffix`, `None` is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(str_strip)] + /// assert_eq!("barfoo".strip_suffix("foo"), Some("bar")); + /// assert_eq!("barfoo".strip_suffix("bar"), None); + /// assert_eq!("foofoo".strip_suffix("foo"), Some("foo")); + /// ``` + #[must_use = "this returns the remaining substring as a new slice, \ + without modifying the original"] + #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")] + pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str> + where + P: Pattern<'a>, +

>::Searcher: ReverseSearcher<'a>, + { + let mut matcher = suffix.into_searcher(self); + if let SearchStep::Match(start, end) = matcher.next_back() { + debug_assert_eq!(end, self.len(), "The first search step from ReverseSearcher \ + must include the last character"); + unsafe { + // Searcher is known to return valid indices. + Some(self.get_unchecked(..start)) + } + } else { + None + } + } + /// Returns a string slice with all suffixes that match a pattern /// repeatedly removed. /// diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index ad9d956fda..b7ebd5f88b 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -3,6 +3,8 @@ //! For more details, see the traits [`Pattern`], [`Searcher`], //! [`ReverseSearcher`], and [`DoubleEndedSearcher`]. +// ignore-tidy-undocumented-unsafe + #![unstable(feature = "pattern", reason = "API not fully fleshed out and ready to be stabilized", issue = "27721")] @@ -294,12 +296,7 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { fn next_match(&mut self) -> Option<(usize, usize)> { loop { // get the haystack after the last character found - let bytes = if let Some(slice) = self.haystack.as_bytes() - .get(self.finger..self.finger_back) { - slice - } else { - return None; - }; + let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?; // the last byte of the utf8 encoded needle let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) }; if let Some(index) = memchr::memchr(last_byte, bytes) { @@ -448,21 +445,13 @@ impl<'a> Pattern<'a> for char { #[inline] fn is_prefix_of(self, haystack: &'a str) -> bool { - if let Some(ch) = haystack.chars().next() { - self == ch - } else { - false - } + self.encode_utf8(&mut [0u8; 4]).is_prefix_of(haystack) } #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a> { - if let Some(ch) = haystack.chars().next_back() { - self == ch - } else { - false - } + self.encode_utf8(&mut [0u8; 4]).is_suffix_of(haystack) } } @@ -713,16 +702,13 @@ impl<'a, 'b> Pattern<'a> for &'b str { /// Checks whether the pattern matches at the front of the haystack #[inline] fn is_prefix_of(self, haystack: &'a str) -> bool { - haystack.is_char_boundary(self.len()) && - self == &haystack[..self.len()] + haystack.as_bytes().starts_with(self.as_bytes()) } /// Checks whether the pattern matches at the back of the haystack #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool { - self.len() <= haystack.len() && - haystack.is_char_boundary(haystack.len() - self.len()) && - self == &haystack[haystack.len() - self.len()..] + haystack.as_bytes().ends_with(self.as_bytes()) } } diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 73d5abf1ae..d5b0bc4203 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -27,7 +27,7 @@ //! //! Atomic variables are safe to share between threads (they implement [`Sync`]) //! but they do not themselves provide the mechanism for sharing and follow the -//! [threading model](../../../std/thread/index.html#the-threading-model) of rust. +//! [threading model](../../../std/thread/index.html#the-threading-model) of Rust. //! The most common way to share an atomic variable is to put it into an [`Arc`][arc] (an //! atomically-reference-counted shared pointer). //! @@ -112,6 +112,8 @@ //! println!("live threads: {}", old_thread_count + 1); //! ``` +// ignore-tidy-undocumented-unsafe + #![stable(feature = "rust1", since = "1.0.0")] #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))] #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))] @@ -160,14 +162,14 @@ pub fn spin_loop_hint() { /// This type has the same in-memory representation as a [`bool`]. /// /// [`bool`]: ../../../std/primitive.bool.html -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "rust1", since = "1.0.0")] #[repr(C, align(1))] pub struct AtomicBool { v: UnsafeCell, } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "rust1", since = "1.0.0")] impl Default for AtomicBool { /// Creates an `AtomicBool` initialized to `false`. @@ -177,14 +179,14 @@ impl Default for AtomicBool { } // Send is implicitly implemented for AtomicBool. -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for AtomicBool {} /// A raw pointer type which can be safely shared between threads. /// /// This type has the same in-memory representation as a `*mut T`. -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] @@ -193,7 +195,7 @@ pub struct AtomicPtr { p: UnsafeCell<*mut T>, } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] impl Default for AtomicPtr { /// Creates a null `AtomicPtr`. @@ -202,10 +204,10 @@ impl Default for AtomicPtr { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for AtomicPtr {} -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for AtomicPtr {} @@ -306,7 +308,7 @@ pub enum Ordering { /// An [`AtomicBool`] initialized to `false`. /// /// [`AtomicBool`]: struct.AtomicBool.html -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( since = "1.34.0", @@ -315,7 +317,7 @@ pub enum Ordering { )] pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false); -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] impl AtomicBool { /// Creates a new `AtomicBool`. /// @@ -329,6 +331,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_atomic_new", since = "1.32.0"))] pub const fn new(v: bool) -> AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } @@ -800,9 +803,46 @@ impl AtomicBool { pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } } + + /// Returns a mutable pointer to the underlying [`bool`]. + /// + /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + /// `*mut bool` instead of `&AtomicBool`. + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the + /// atomic types work with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same + /// restriction: operations on it must be atomic. + /// + /// [`bool`]: ../../../std/primitive.bool.html + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// # fn main() { + /// use std::sync::atomic::AtomicBool; + /// extern { + /// fn my_atomic_op(arg: *mut bool); + /// } + /// + /// let mut atomic = AtomicBool::new(true); + /// unsafe { + /// my_atomic_op(atomic.as_mut_ptr()); + /// } + /// # } + /// ``` + #[inline] + #[unstable(feature = "atomic_mut_ptr", + reason = "recently added", + issue = "66893")] + pub fn as_mut_ptr(&self) -> *mut bool { + self.v.get() as *mut bool + } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] impl AtomicPtr { /// Creates a new `AtomicPtr`. /// @@ -816,6 +856,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "const_atomic_new", since = "1.32.0"))] pub const fn new(p: *mut T) -> AtomicPtr { AtomicPtr { p: UnsafeCell::new(p) } } @@ -1112,7 +1153,7 @@ impl AtomicPtr { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "atomic_bool_from", since = "1.24.0")] impl From for AtomicBool { /// Converts a `bool` into an `AtomicBool`. @@ -1128,14 +1169,14 @@ impl From for AtomicBool { fn from(b: bool) -> Self { Self::new(b) } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "atomic_from", since = "1.23.0")] impl From<*mut T> for AtomicPtr { #[inline] fn from(p: *mut T) -> Self { Self::new(p) } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] macro_rules! atomic_int { ($cfg_cas:meta, $stable:meta, @@ -1144,6 +1185,7 @@ macro_rules! atomic_int { $stable_access:meta, $stable_from:meta, $stable_nand:meta, + $const_stable:meta, $stable_init_const:meta, $s_int_type:expr, $int_ref:expr, $extra_feature:expr, @@ -1219,8 +1261,9 @@ let atomic_forty_two = ", stringify!($atomic_type), "::new(42); ```"), #[inline] #[$stable] + #[cfg_attr(not(bootstrap), $const_stable)] pub const fn new(v: $int_type) -> Self { - $atomic_type {v: UnsafeCell::new(v)} + Self {v: UnsafeCell::new(v)} } } @@ -1889,11 +1932,48 @@ assert_eq!(min_foo, 12); } } + doc_comment! { + concat!("Returns a mutable pointer to the underlying integer. + +Doing non-atomic reads and writes on the resulting integer can be a data race. +This method is mostly useful for FFI, where the function signature may use +`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`. + +Returning an `*mut` pointer from a shared reference to this atomic is safe because the +atomic types work with interior mutability. All modifications of an atomic change the value +through a shared reference, and can do so safely as long as they use atomic operations. Any +use of the returned raw pointer requires an `unsafe` block and still has to uphold the same +restriction: operations on it must be atomic. + +# Examples + +```ignore (extern-declaration) +# fn main() { +", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), "; + +extern { + fn my_atomic_op(arg: *mut ", stringify!($int_type), "); +} + +let mut atomic = ", stringify!($atomic_type), "::new(1); +unsafe { + my_atomic_op(atomic.as_mut_ptr()); +} +# } +```"), + #[inline] + #[unstable(feature = "atomic_mut_ptr", + reason = "recently added", + issue = "66893")] + pub fn as_mut_ptr(&self) -> *mut $int_type { + self.v.get() + } + } } } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] atomic_int! { cfg(target_has_atomic = "8"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1902,6 +1982,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i8", "../../../std/primitive.i8.html", "", @@ -1910,7 +1991,7 @@ atomic_int! { "AtomicI8::new(0)", i8 AtomicI8 ATOMIC_I8_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] atomic_int! { cfg(target_has_atomic = "8"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1919,6 +2000,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u8", "../../../std/primitive.u8.html", "", @@ -1927,7 +2009,7 @@ atomic_int! { "AtomicU8::new(0)", u8 AtomicU8 ATOMIC_U8_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))] +#[cfg(target_has_atomic_load_store = "16")] atomic_int! { cfg(target_has_atomic = "16"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1936,6 +2018,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i16", "../../../std/primitive.i16.html", "", @@ -1944,7 +2027,7 @@ atomic_int! { "AtomicI16::new(0)", i16 AtomicI16 ATOMIC_I16_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))] +#[cfg(target_has_atomic_load_store = "16")] atomic_int! { cfg(target_has_atomic = "16"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1953,6 +2036,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u16", "../../../std/primitive.u16.html", "", @@ -1961,7 +2045,7 @@ atomic_int! { "AtomicU16::new(0)", u16 AtomicU16 ATOMIC_U16_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))] +#[cfg(target_has_atomic_load_store = "32")] atomic_int! { cfg(target_has_atomic = "32"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1970,6 +2054,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i32", "../../../std/primitive.i32.html", "", @@ -1978,7 +2063,7 @@ atomic_int! { "AtomicI32::new(0)", i32 AtomicI32 ATOMIC_I32_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))] +#[cfg(target_has_atomic_load_store = "32")] atomic_int! { cfg(target_has_atomic = "32"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1987,6 +2072,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u32", "../../../std/primitive.u32.html", "", @@ -1995,10 +2081,7 @@ atomic_int! { "AtomicU32::new(0)", u32 AtomicU32 ATOMIC_U32_INIT } -#[cfg(any( - all(bootstrap, target_has_atomic = "64"), - target_has_atomic_load_store = "64" -))] +#[cfg(target_has_atomic_load_store = "64")] atomic_int! { cfg(target_has_atomic = "64"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -2007,6 +2090,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i64", "../../../std/primitive.i64.html", "", @@ -2015,10 +2099,7 @@ atomic_int! { "AtomicI64::new(0)", i64 AtomicI64 ATOMIC_I64_INIT } -#[cfg(any( - all(bootstrap, target_has_atomic = "64"), - target_has_atomic_load_store = "64" -))] +#[cfg(target_has_atomic_load_store = "64")] atomic_int! { cfg(target_has_atomic = "64"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -2027,6 +2108,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u64", "../../../std/primitive.u64.html", "", @@ -2044,6 +2126,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "i128", "../../../std/primitive.i128.html", "#![feature(integer_atomics)]\n\n", @@ -2061,6 +2144,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), unstable(feature = "integer_atomics", issue = "32976"), "u128", "../../../std/primitive.u128.html", "#![feature(integer_atomics)]\n\n", @@ -2069,22 +2153,22 @@ atomic_int! { "AtomicU128::new(0)", u128 AtomicU128 ATOMIC_U128_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[cfg(target_pointer_width = "16")] macro_rules! ptr_width { () => { 2 } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[cfg(target_pointer_width = "32")] macro_rules! ptr_width { () => { 4 } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[cfg(target_pointer_width = "64")] macro_rules! ptr_width { () => { 8 } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] atomic_int!{ cfg(target_has_atomic = "ptr"), stable(feature = "rust1", since = "1.0.0"), @@ -2093,6 +2177,7 @@ atomic_int!{ stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), stable(feature = "rust1", since = "1.0.0"), "isize", "../../../std/primitive.isize.html", "", @@ -2101,7 +2186,7 @@ atomic_int!{ "AtomicIsize::new(0)", isize AtomicIsize ATOMIC_ISIZE_INIT } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] atomic_int!{ cfg(target_has_atomic = "ptr"), stable(feature = "rust1", since = "1.0.0"), @@ -2110,6 +2195,7 @@ atomic_int!{ stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), + rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), stable(feature = "rust1", since = "1.0.0"), "usize", "../../../std/primitive.usize.html", "", @@ -2528,7 +2614,7 @@ pub fn compiler_fence(order: Ordering) { } -#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] +#[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "atomic_debug", since = "1.3.0")] impl fmt::Debug for AtomicBool { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2536,7 +2622,7 @@ impl fmt::Debug for AtomicBool { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "atomic_debug", since = "1.3.0")] impl fmt::Debug for AtomicPtr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2544,7 +2630,7 @@ impl fmt::Debug for AtomicPtr { } } -#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "atomic_pointer", since = "1.24.0")] impl fmt::Pointer for AtomicPtr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index ef09092839..27760749c1 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -8,4 +8,4 @@ pub use self::poll::Poll; mod wake; #[stable(feature = "futures_api", since = "1.36.0")] -pub use self::wake::{Context, Waker, RawWaker, RawWakerVTable}; +pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs index fec17c4d1a..d567ae5457 100644 --- a/src/libcore/task/poll.rs +++ b/src/libcore/task/poll.rs @@ -11,10 +11,7 @@ use crate::result::Result; pub enum Poll { /// Represents that a value is immediately ready. #[stable(feature = "futures_api", since = "1.36.0")] - Ready( - #[stable(feature = "futures_api", since = "1.36.0")] - T - ), + Ready(#[stable(feature = "futures_api", since = "1.36.0")] T), /// Represents that a value is not ready yet. /// @@ -29,7 +26,8 @@ impl Poll { /// Changes the ready value of this `Poll` with the closure provided. #[stable(feature = "futures_api", since = "1.36.0")] pub fn map(self, f: F) -> Poll - where F: FnOnce(T) -> U + where + F: FnOnce(T) -> U, { match self { Poll::Ready(t) => Poll::Ready(f(t)), @@ -59,7 +57,8 @@ impl Poll> { /// Changes the success value of this `Poll` with the closure provided. #[stable(feature = "futures_api", since = "1.36.0")] pub fn map_ok(self, f: F) -> Poll> - where F: FnOnce(T) -> U + where + F: FnOnce(T) -> U, { match self { Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))), @@ -71,7 +70,8 @@ impl Poll> { /// Changes the error value of this `Poll` with the closure provided. #[stable(feature = "futures_api", since = "1.36.0")] pub fn map_err(self, f: F) -> Poll> - where F: FnOnce(E) -> U + where + F: FnOnce(E) -> U, { match self { Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)), @@ -85,7 +85,8 @@ impl Poll>> { /// Changes the success value of this `Poll` with the closure provided. #[unstable(feature = "poll_map", issue = "63514")] pub fn map_ok(self, f: F) -> Poll>> - where F: FnOnce(T) -> U + where + F: FnOnce(T) -> U, { match self { Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))), @@ -98,7 +99,8 @@ impl Poll>> { /// Changes the error value of this `Poll` with the closure provided. #[unstable(feature = "poll_map", issue = "63514")] pub fn map_err(self, f: F) -> Poll>> - where F: FnOnce(E) -> U + where + F: FnOnce(E) -> U, { match self { Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))), diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 6f841bd2ad..c1e45f189b 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -39,11 +39,9 @@ impl RawWaker { /// function in the `vtable` of the underlying `RawWaker` will be called. #[rustc_promotable] #[stable(feature = "futures_api", since = "1.36.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "futures_api", since = "1.36.0"))] pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker { - RawWaker { - data, - vtable, - } + RawWaker { data, vtable } } } @@ -154,18 +152,14 @@ impl RawWakerVTable { // FIXME: remove whenever we have a stable way to accept fn pointers from const fn // (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062) #[rustc_allow_const_fn_ptr] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "futures_api", since = "1.36.0"))] pub const fn new( clone: unsafe fn(*const ()) -> RawWaker, wake: unsafe fn(*const ()), wake_by_ref: unsafe fn(*const ()), drop: unsafe fn(*const ()), ) -> Self { - Self { - clone, - wake, - wake_by_ref, - drop, - } + Self { clone, wake, wake_by_ref, drop } } } @@ -188,10 +182,7 @@ impl<'a> Context<'a> { #[stable(feature = "futures_api", since = "1.36.0")] #[inline] pub fn from_waker(waker: &'a Waker) -> Self { - Context { - waker, - _marker: PhantomData, - } + Context { waker, _marker: PhantomData } } /// Returns a reference to the `Waker` for the current task. @@ -205,9 +196,7 @@ impl<'a> Context<'a> { #[stable(feature = "futures_api", since = "1.36.0")] impl fmt::Debug for Context<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Context") - .field("waker", &self.waker) - .finish() + f.debug_struct("Context").field("waker", &self.waker).finish() } } @@ -291,9 +280,7 @@ impl Waker { #[inline] #[stable(feature = "futures_api", since = "1.36.0")] pub unsafe fn from_raw(waker: RawWaker) -> Waker { - Waker { - waker, - } + Waker { waker } } } diff --git a/src/libcore/tests/any.rs b/src/libcore/tests/any.rs index 62bebcb03c..b0dc990346 100644 --- a/src/libcore/tests/any.rs +++ b/src/libcore/tests/any.rs @@ -24,11 +24,8 @@ fn any_referenced() { #[test] fn any_owning() { - let (a, b, c) = ( - box 5_usize as Box, - box TEST as Box, - box Test as Box, - ); + let (a, b, c) = + (box 5_usize as Box, box TEST as Box, box Test as Box); assert!(a.is::()); assert!(!b.is::()); @@ -49,12 +46,12 @@ fn any_downcast_ref() { match a.downcast_ref::() { Some(&5) => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match a.downcast_ref::() { None => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } } @@ -72,7 +69,7 @@ fn any_downcast_mut() { assert_eq!(*x, 5); *x = 612; } - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match b_r.downcast_mut::() { @@ -80,27 +77,27 @@ fn any_downcast_mut() { assert_eq!(*x, 7); *x = 413; } - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match a_r.downcast_mut::() { None => (), - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match b_r.downcast_mut::() { None => (), - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match a_r.downcast_mut::() { Some(&mut 612) => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } match b_r.downcast_mut::() { Some(&mut 413) => {} - x => panic!("Unexpected value {:?}", x) + x => panic!("Unexpected value {:?}", x), } } diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs index 4f3b79c78b..c2a816f0a7 100644 --- a/src/libcore/tests/array.rs +++ b/src/libcore/tests/array.rs @@ -41,7 +41,6 @@ fn array_try_from() { } } - #[test] fn iterator_collect() { let arr = [0, 1, 2, 5, 9]; @@ -150,10 +149,7 @@ fn iterator_flat_map() { #[test] fn iterator_debug() { let arr = [0, 1, 2, 5, 9]; - assert_eq!( - format!("{:?}", IntoIter::new(arr)), - "IntoIter([0, 1, 2, 5, 9])", - ); + assert_eq!(format!("{:?}", IntoIter::new(arr)), "IntoIter([0, 1, 2, 5, 9])",); } #[test] @@ -168,7 +164,7 @@ fn iterator_drops() { struct Foo<'a>(&'a Cell); impl Drop for Foo<'_> { - fn drop(&mut self) { + fn drop(&mut self) { self.0.set(self.0.get() + 1); } } diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs index 439ed0c81c..71275d40c4 100644 --- a/src/libcore/tests/ascii.rs +++ b/src/libcore/tests/ascii.rs @@ -22,10 +22,12 @@ fn test_to_ascii_uppercase() { assert_eq!("hıKß".to_ascii_uppercase(), "HıKß"); for i in 0..501 { - let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } - else { i }; - assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(), - (from_u32(upper).unwrap()).to_string()); + let upper = + if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; + assert_eq!( + (from_u32(i).unwrap()).to_string().to_ascii_uppercase(), + (from_u32(upper).unwrap()).to_string() + ); } } @@ -36,23 +38,23 @@ fn test_to_ascii_lowercase() { assert_eq!("HİKß".to_ascii_lowercase(), "hİKß"); for i in 0..501 { - let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } - else { i }; - assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(), - (from_u32(lower).unwrap()).to_string()); + let lower = + if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; + assert_eq!( + (from_u32(i).unwrap()).to_string().to_ascii_lowercase(), + (from_u32(lower).unwrap()).to_string() + ); } } #[test] fn test_make_ascii_lower_case() { macro_rules! test { - ($from: expr, $to: expr) => { - { - let mut x = $from; - x.make_ascii_lowercase(); - assert_eq!(x, $to); - } - } + ($from: expr, $to: expr) => {{ + let mut x = $from; + x.make_ascii_lowercase(); + assert_eq!(x, $to); + }}; } test!(b'A', b'a'); test!(b'a', b'a'); @@ -65,17 +67,14 @@ fn test_make_ascii_lower_case() { test!("HİKß".to_string(), "hİKß"); } - #[test] fn test_make_ascii_upper_case() { macro_rules! test { - ($from: expr, $to: expr) => { - { - let mut x = $from; - x.make_ascii_uppercase(); - assert_eq!(x, $to); - } - } + ($from: expr, $to: expr) => {{ + let mut x = $from; + x.make_ascii_uppercase(); + assert_eq!(x, $to); + }}; } test!(b'a', b'A'); test!(b'A', b'A'); @@ -88,7 +87,7 @@ fn test_make_ascii_upper_case() { test!("hıKß".to_string(), "HıKß"); let mut x = "Hello".to_string(); - x[..3].make_ascii_uppercase(); // Test IndexMut on String. + x[..3].make_ascii_uppercase(); // Test IndexMut on String. assert_eq!(x, "HELlo") } @@ -103,10 +102,13 @@ fn test_eq_ignore_ascii_case() { assert!(!"ß".eq_ignore_ascii_case("s")); for i in 0..501 { - let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } - else { i }; - assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case( - &from_u32(lower).unwrap().to_string())); + let lower = + if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; + assert!( + (from_u32(i).unwrap()) + .to_string() + .eq_ignore_ascii_case(&from_u32(lower).unwrap().to_string()) + ); } } @@ -158,12 +160,14 @@ macro_rules! assert_none { #[test] fn test_is_ascii_alphabetic() { - assert_all!(is_ascii_alphabetic, + assert_all!( + is_ascii_alphabetic, "", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOQPRSTUVWXYZ", ); - assert_none!(is_ascii_alphabetic, + assert_none!( + is_ascii_alphabetic, "0123456789", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", " \t\n\x0c\r", @@ -177,11 +181,9 @@ fn test_is_ascii_alphabetic() { #[test] fn test_is_ascii_uppercase() { - assert_all!(is_ascii_uppercase, - "", - "ABCDEFGHIJKLMNOQPRSTUVWXYZ", - ); - assert_none!(is_ascii_uppercase, + assert_all!(is_ascii_uppercase, "", "ABCDEFGHIJKLMNOQPRSTUVWXYZ",); + assert_none!( + is_ascii_uppercase, "abcdefghijklmnopqrstuvwxyz", "0123456789", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", @@ -196,10 +198,9 @@ fn test_is_ascii_uppercase() { #[test] fn test_is_ascii_lowercase() { - assert_all!(is_ascii_lowercase, - "abcdefghijklmnopqrstuvwxyz", - ); - assert_none!(is_ascii_lowercase, + assert_all!(is_ascii_lowercase, "abcdefghijklmnopqrstuvwxyz",); + assert_none!( + is_ascii_lowercase, "ABCDEFGHIJKLMNOQPRSTUVWXYZ", "0123456789", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", @@ -214,13 +215,15 @@ fn test_is_ascii_lowercase() { #[test] fn test_is_ascii_alphanumeric() { - assert_all!(is_ascii_alphanumeric, + assert_all!( + is_ascii_alphanumeric, "", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOQPRSTUVWXYZ", "0123456789", ); - assert_none!(is_ascii_alphanumeric, + assert_none!( + is_ascii_alphanumeric, "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", " \t\n\x0c\r", "\x00\x01\x02\x03\x04\x05\x06\x07", @@ -233,11 +236,9 @@ fn test_is_ascii_alphanumeric() { #[test] fn test_is_ascii_digit() { - assert_all!(is_ascii_digit, - "", - "0123456789", - ); - assert_none!(is_ascii_digit, + assert_all!(is_ascii_digit, "", "0123456789",); + assert_none!( + is_ascii_digit, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOQPRSTUVWXYZ", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", @@ -252,12 +253,9 @@ fn test_is_ascii_digit() { #[test] fn test_is_ascii_hexdigit() { - assert_all!(is_ascii_hexdigit, - "", - "0123456789", - "abcdefABCDEF", - ); - assert_none!(is_ascii_hexdigit, + assert_all!(is_ascii_hexdigit, "", "0123456789", "abcdefABCDEF",); + assert_none!( + is_ascii_hexdigit, "ghijklmnopqrstuvwxyz", "GHIJKLMNOQPRSTUVWXYZ", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", @@ -272,11 +270,9 @@ fn test_is_ascii_hexdigit() { #[test] fn test_is_ascii_punctuation() { - assert_all!(is_ascii_punctuation, - "", - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", - ); - assert_none!(is_ascii_punctuation, + assert_all!(is_ascii_punctuation, "", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",); + assert_none!( + is_ascii_punctuation, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOQPRSTUVWXYZ", "0123456789", @@ -291,14 +287,16 @@ fn test_is_ascii_punctuation() { #[test] fn test_is_ascii_graphic() { - assert_all!(is_ascii_graphic, + assert_all!( + is_ascii_graphic, "", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOQPRSTUVWXYZ", "0123456789", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", ); - assert_none!(is_ascii_graphic, + assert_none!( + is_ascii_graphic, " \t\n\x0c\r", "\x00\x01\x02\x03\x04\x05\x06\x07", "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", @@ -310,11 +308,9 @@ fn test_is_ascii_graphic() { #[test] fn test_is_ascii_whitespace() { - assert_all!(is_ascii_whitespace, - "", - " \t\n\x0c\r", - ); - assert_none!(is_ascii_whitespace, + assert_all!(is_ascii_whitespace, "", " \t\n\x0c\r",); + assert_none!( + is_ascii_whitespace, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOQPRSTUVWXYZ", "0123456789", @@ -329,7 +325,8 @@ fn test_is_ascii_whitespace() { #[test] fn test_is_ascii_control() { - assert_all!(is_ascii_control, + assert_all!( + is_ascii_control, "", "\x00\x01\x02\x03\x04\x05\x06\x07", "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", @@ -337,7 +334,8 @@ fn test_is_ascii_control() { "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", "\x7f", ); - assert_none!(is_ascii_control, + assert_none!( + is_ascii_control, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOQPRSTUVWXYZ", "0123456789", diff --git a/src/libcore/tests/atomic.rs b/src/libcore/tests/atomic.rs index 05fe8460f3..acbd913982 100644 --- a/src/libcore/tests/atomic.rs +++ b/src/libcore/tests/atomic.rs @@ -1,5 +1,5 @@ -use core::sync::atomic::*; use core::sync::atomic::Ordering::SeqCst; +use core::sync::atomic::*; #[test] fn bool_() { @@ -15,7 +15,7 @@ fn bool_() { fn bool_and() { let a = AtomicBool::new(true); assert_eq!(a.fetch_and(false, SeqCst), true); - assert_eq!(a.load(SeqCst),false); + assert_eq!(a.load(SeqCst), false); } #[test] @@ -89,7 +89,7 @@ fn int_xor() { static S_FALSE: AtomicBool = AtomicBool::new(false); static S_TRUE: AtomicBool = AtomicBool::new(true); -static S_INT: AtomicIsize = AtomicIsize::new(0); +static S_INT: AtomicIsize = AtomicIsize::new(0); static S_UINT: AtomicUsize = AtomicUsize::new(0); #[test] diff --git a/src/libcore/tests/bool.rs b/src/libcore/tests/bool.rs index 0f1e6e8945..e89eb2c7f9 100644 --- a/src/libcore/tests/bool.rs +++ b/src/libcore/tests/bool.rs @@ -1,7 +1,7 @@ #[test] fn test_bool_to_option() { - assert_eq!(false.then(0), None); - assert_eq!(true.then(0), Some(0)); - assert_eq!(false.then_with(|| 0), None); - assert_eq!(true.then_with(|| 0), Some(0)); + assert_eq!(false.then_some(0), None); + assert_eq!(true.then_some(0), Some(0)); + assert_eq!(false.then(|| 0), None); + assert_eq!(true.then(|| 0), Some(0)); } diff --git a/src/libcore/tests/cell.rs b/src/libcore/tests/cell.rs index 4dfd884d23..801b60be0f 100644 --- a/src/libcore/tests/cell.rs +++ b/src/libcore/tests/cell.rs @@ -236,7 +236,7 @@ fn ref_mut_map_accessor() { } let x = X(RefCell::new((7, 'z'))); { - let mut d: RefMut<'_ ,u32> = x.accessor(); + let mut d: RefMut<'_, u32> = x.accessor(); assert_eq!(*d, 7); *d += 1; } @@ -250,7 +250,9 @@ fn as_ptr() { assert_eq!(1, unsafe { *c1.as_ptr() }); let c2: Cell = Cell::new(0); - unsafe { *c2.as_ptr() = 1; } + unsafe { + *c2.as_ptr() = 1; + } assert_eq!(1, c2.get()); let r1: RefCell = RefCell::new(0); @@ -258,7 +260,9 @@ fn as_ptr() { assert_eq!(1, unsafe { *r1.as_ptr() }); let r2: RefCell = RefCell::new(0); - unsafe { *r2.as_ptr() = 1; } + unsafe { + *r2.as_ptr() = 1; + } assert_eq!(1, *r2.borrow()); } diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs index 57e9f4e384..c16f54081c 100644 --- a/src/libcore/tests/char.rs +++ b/src/libcore/tests/char.rs @@ -1,6 +1,6 @@ -use std::{char,str}; use std::convert::TryFrom; use std::str::FromStr; +use std::{char, str}; #[test] fn test_convert() { @@ -143,13 +143,13 @@ fn test_is_control() { #[test] fn test_is_numeric() { - assert!('2'.is_numeric()); - assert!('7'.is_numeric()); - assert!('¾'.is_numeric()); - assert!(!'c'.is_numeric()); - assert!(!'i'.is_numeric()); - assert!(!'z'.is_numeric()); - assert!(!'Q'.is_numeric()); + assert!('2'.is_numeric()); + assert!('7'.is_numeric()); + assert!('¾'.is_numeric()); + assert!(!'c'.is_numeric()); + assert!(!'i'.is_numeric()); + assert!(!'z'.is_numeric()); + assert!(!'Q'.is_numeric()); } #[test] @@ -176,9 +176,9 @@ fn test_escape_debug() { assert_eq!(string('\u{ff}'), "\u{ff}"); assert_eq!(string('\u{11b}'), "\u{11b}"); assert_eq!(string('\u{1d4b6}'), "\u{1d4b6}"); - assert_eq!(string('\u{301}'), "\\u{301}"); // combining character - assert_eq!(string('\u{200b}'),"\\u{200b}"); // zero width space - assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1 + assert_eq!(string('\u{301}'), "\\u{301}"); // combining character + assert_eq!(string('\u{200b}'), "\\u{200b}"); // zero width space + assert_eq!(string('\u{e000}'), "\\u{e000}"); // private use 1 assert_eq!(string('\u{100000}'), "\\u{100000}"); // private use 2 } @@ -272,8 +272,8 @@ fn test_len_utf16() { fn test_decode_utf16() { fn check(s: &[u16], expected: &[Result]) { let v = char::decode_utf16(s.iter().cloned()) - .map(|r| r.map_err(|e| e.unpaired_surrogate())) - .collect::>(); + .map(|r| r.map_err(|e| e.unpaired_surrogate())) + .collect::>(); assert_eq!(v, expected); } check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]); diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs index 5e6778e222..56a2f4acf6 100644 --- a/src/libcore/tests/cmp.rs +++ b/src/libcore/tests/cmp.rs @@ -9,6 +9,14 @@ fn test_int_totalord() { assert_eq!(12.cmp(&-5), Greater); } +#[test] +fn test_bool_totalord() { + assert_eq!(true.cmp(&false), Greater); + assert_eq!(false.cmp(&true), Less); + assert_eq!(true.cmp(&true), Equal); + assert_eq!(false.cmp(&false), Equal); +} + #[test] fn test_mut_int_totalord() { assert_eq!((&mut 5).cmp(&&mut 10), Less); diff --git a/src/libcore/tests/hash/mod.rs b/src/libcore/tests/hash/mod.rs index 1000088e6b..ba0220f0d9 100644 --- a/src/libcore/tests/hash/mod.rs +++ b/src/libcore/tests/hash/mod.rs @@ -1,7 +1,7 @@ mod sip; -use std::hash::{Hash, Hasher}; use std::default::Default; +use std::hash::{Hash, Hasher}; use std::rc::Rc; struct MyHasher { @@ -20,10 +20,11 @@ impl Hasher for MyHasher { self.hash += *byte as u64; } } - fn finish(&self) -> u64 { self.hash } + fn finish(&self) -> u64 { + self.hash + } } - #[test] fn test_writer_hasher() { fn hash(t: &T) -> u64 { @@ -52,17 +53,17 @@ fn test_writer_hasher() { assert_eq!(hash(&'a'), 97); let s: &str = "a"; - assert_eq!(hash(& s), 97 + 0xFF); + assert_eq!(hash(&s), 97 + 0xFF); let s: Box = String::from("a").into_boxed_str(); - assert_eq!(hash(& s), 97 + 0xFF); + assert_eq!(hash(&s), 97 + 0xFF); let s: Rc<&str> = Rc::new("a"); assert_eq!(hash(&s), 97 + 0xFF); let cs: &[u8] = &[1, 2, 3]; - assert_eq!(hash(& cs), 9); + assert_eq!(hash(&cs), 9); let cs: Box<[u8]> = Box::new([1, 2, 3]); - assert_eq!(hash(& cs), 9); + assert_eq!(hash(&cs), 9); let cs: Rc<[u8]> = Rc::new([1, 2, 3]); - assert_eq!(hash(& cs), 9); + assert_eq!(hash(&cs), 9); let ptr = 5_usize as *const i32; assert_eq!(hash(&ptr), 5); @@ -70,24 +71,36 @@ fn test_writer_hasher() { let ptr = 5_usize as *mut i32; assert_eq!(hash(&ptr), 5); + if cfg!(miri) { // Miri cannot hash pointers + return; + } + let cs: &mut [u8] = &mut [1, 2, 3]; let ptr = cs.as_ptr(); let slice_ptr = cs as *const [u8]; - #[cfg(not(miri))] // Miri cannot hash pointers assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64); let slice_ptr = cs as *mut [u8]; - #[cfg(not(miri))] // Miri cannot hash pointers assert_eq!(hash(&slice_ptr), hash(&ptr) + cs.len() as u64); } -struct Custom { hash: u64 } -struct CustomHasher { output: u64 } +struct Custom { + hash: u64, +} +struct CustomHasher { + output: u64, +} impl Hasher for CustomHasher { - fn finish(&self) -> u64 { self.output } - fn write(&mut self, _: &[u8]) { panic!() } - fn write_u64(&mut self, data: u64) { self.output = data; } + fn finish(&self) -> u64 { + self.output + } + fn write(&mut self, _: &[u8]) { + panic!() + } + fn write_u64(&mut self, data: u64) { + self.output = data; + } } impl Default for CustomHasher { diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs index b615cfd77e..0f09554991 100644 --- a/src/libcore/tests/hash/sip.rs +++ b/src/libcore/tests/hash/sip.rs @@ -2,7 +2,7 @@ use core::hash::{Hash, Hasher}; use core::hash::{SipHasher, SipHasher13}; -use core::{slice, mem}; +use core::{mem, slice}; // Hash just the bytes of the slice, without length prefix struct Bytes<'a>(&'a [u8]); @@ -16,25 +16,25 @@ impl<'a> Hash for Bytes<'a> { } macro_rules! u8to64_le { - ($buf:expr, $i:expr) => - ($buf[0+$i] as u64 | - ($buf[1+$i] as u64) << 8 | - ($buf[2+$i] as u64) << 16 | - ($buf[3+$i] as u64) << 24 | - ($buf[4+$i] as u64) << 32 | - ($buf[5+$i] as u64) << 40 | - ($buf[6+$i] as u64) << 48 | - ($buf[7+$i] as u64) << 56); - ($buf:expr, $i:expr, $len:expr) => - ({ + ($buf:expr, $i:expr) => { + $buf[0 + $i] as u64 + | ($buf[1 + $i] as u64) << 8 + | ($buf[2 + $i] as u64) << 16 + | ($buf[3 + $i] as u64) << 24 + | ($buf[4 + $i] as u64) << 32 + | ($buf[5 + $i] as u64) << 40 + | ($buf[6 + $i] as u64) << 48 + | ($buf[7 + $i] as u64) << 56 + }; + ($buf:expr, $i:expr, $len:expr) => {{ let mut t = 0; let mut out = 0; while t < $len { - out |= ($buf[t+$i] as u64) << t*8; + out |= ($buf[t + $i] as u64) << t * 8; t += 1; } out - }); + }}; } fn hash_with(mut st: H, x: &T) -> u64 { @@ -49,71 +49,71 @@ fn hash(x: &T) -> u64 { #[test] #[allow(unused_must_use)] fn test_siphash_1_3() { - let vecs : [[u8; 8]; 64] = [ - [ 0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab ], - [ 0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9 ], - [ 0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82 ], - [ 0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b ], - [ 0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf ], - [ 0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde ], - [ 0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5 ], - [ 0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3 ], - [ 0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36 ], - [ 0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25 ], - [ 0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79 ], - [ 0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70 ], - [ 0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78 ], - [ 0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30 ], - [ 0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60 ], - [ 0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3 ], - [ 0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc ], - [ 0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c ], - [ 0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f ], - [ 0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2 ], - [ 0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0 ], - [ 0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9 ], - [ 0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f ], - [ 0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52 ], - [ 0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4 ], - [ 0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45 ], - [ 0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a ], - [ 0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9 ], - [ 0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb ], - [ 0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88 ], - [ 0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54 ], - [ 0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23 ], - [ 0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81 ], - [ 0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d ], - [ 0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75 ], - [ 0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce ], - [ 0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c ], - [ 0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6 ], - [ 0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3 ], - [ 0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62 ], - [ 0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1 ], - [ 0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66 ], - [ 0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65 ], - [ 0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24 ], - [ 0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2 ], - [ 0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2 ], - [ 0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1 ], - [ 0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49 ], - [ 0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f ], - [ 0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6 ], - [ 0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e ], - [ 0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c ], - [ 0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4 ], - [ 0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36 ], - [ 0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31 ], - [ 0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2 ], - [ 0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4 ], - [ 0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23 ], - [ 0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f ], - [ 0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8 ], - [ 0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6 ], - [ 0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae ], - [ 0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3 ], - [ 0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d ] + let vecs: [[u8; 8]; 64] = [ + [0xdc, 0xc4, 0x0f, 0x05, 0x58, 0x01, 0xac, 0xab], + [0x93, 0xca, 0x57, 0x7d, 0xf3, 0x9b, 0xf4, 0xc9], + [0x4d, 0xd4, 0xc7, 0x4d, 0x02, 0x9b, 0xcb, 0x82], + [0xfb, 0xf7, 0xdd, 0xe7, 0xb8, 0x0a, 0xf8, 0x8b], + [0x28, 0x83, 0xd3, 0x88, 0x60, 0x57, 0x75, 0xcf], + [0x67, 0x3b, 0x53, 0x49, 0x2f, 0xd5, 0xf9, 0xde], + [0xa7, 0x22, 0x9f, 0xc5, 0x50, 0x2b, 0x0d, 0xc5], + [0x40, 0x11, 0xb1, 0x9b, 0x98, 0x7d, 0x92, 0xd3], + [0x8e, 0x9a, 0x29, 0x8d, 0x11, 0x95, 0x90, 0x36], + [0xe4, 0x3d, 0x06, 0x6c, 0xb3, 0x8e, 0xa4, 0x25], + [0x7f, 0x09, 0xff, 0x92, 0xee, 0x85, 0xde, 0x79], + [0x52, 0xc3, 0x4d, 0xf9, 0xc1, 0x18, 0xc1, 0x70], + [0xa2, 0xd9, 0xb4, 0x57, 0xb1, 0x84, 0xa3, 0x78], + [0xa7, 0xff, 0x29, 0x12, 0x0c, 0x76, 0x6f, 0x30], + [0x34, 0x5d, 0xf9, 0xc0, 0x11, 0xa1, 0x5a, 0x60], + [0x56, 0x99, 0x51, 0x2a, 0x6d, 0xd8, 0x20, 0xd3], + [0x66, 0x8b, 0x90, 0x7d, 0x1a, 0xdd, 0x4f, 0xcc], + [0x0c, 0xd8, 0xdb, 0x63, 0x90, 0x68, 0xf2, 0x9c], + [0x3e, 0xe6, 0x73, 0xb4, 0x9c, 0x38, 0xfc, 0x8f], + [0x1c, 0x7d, 0x29, 0x8d, 0xe5, 0x9d, 0x1f, 0xf2], + [0x40, 0xe0, 0xcc, 0xa6, 0x46, 0x2f, 0xdc, 0xc0], + [0x44, 0xf8, 0x45, 0x2b, 0xfe, 0xab, 0x92, 0xb9], + [0x2e, 0x87, 0x20, 0xa3, 0x9b, 0x7b, 0xfe, 0x7f], + [0x23, 0xc1, 0xe6, 0xda, 0x7f, 0x0e, 0x5a, 0x52], + [0x8c, 0x9c, 0x34, 0x67, 0xb2, 0xae, 0x64, 0xf4], + [0x79, 0x09, 0x5b, 0x70, 0x28, 0x59, 0xcd, 0x45], + [0xa5, 0x13, 0x99, 0xca, 0xe3, 0x35, 0x3e, 0x3a], + [0x35, 0x3b, 0xde, 0x4a, 0x4e, 0xc7, 0x1d, 0xa9], + [0x0d, 0xd0, 0x6c, 0xef, 0x02, 0xed, 0x0b, 0xfb], + [0xf4, 0xe1, 0xb1, 0x4a, 0xb4, 0x3c, 0xd9, 0x88], + [0x63, 0xe6, 0xc5, 0x43, 0xd6, 0x11, 0x0f, 0x54], + [0xbc, 0xd1, 0x21, 0x8c, 0x1f, 0xdd, 0x70, 0x23], + [0x0d, 0xb6, 0xa7, 0x16, 0x6c, 0x7b, 0x15, 0x81], + [0xbf, 0xf9, 0x8f, 0x7a, 0xe5, 0xb9, 0x54, 0x4d], + [0x3e, 0x75, 0x2a, 0x1f, 0x78, 0x12, 0x9f, 0x75], + [0x91, 0x6b, 0x18, 0xbf, 0xbe, 0xa3, 0xa1, 0xce], + [0x06, 0x62, 0xa2, 0xad, 0xd3, 0x08, 0xf5, 0x2c], + [0x57, 0x30, 0xc3, 0xa3, 0x2d, 0x1c, 0x10, 0xb6], + [0xa1, 0x36, 0x3a, 0xae, 0x96, 0x74, 0xf4, 0xb3], + [0x92, 0x83, 0x10, 0x7b, 0x54, 0x57, 0x6b, 0x62], + [0x31, 0x15, 0xe4, 0x99, 0x32, 0x36, 0xd2, 0xc1], + [0x44, 0xd9, 0x1a, 0x3f, 0x92, 0xc1, 0x7c, 0x66], + [0x25, 0x88, 0x13, 0xc8, 0xfe, 0x4f, 0x70, 0x65], + [0xa6, 0x49, 0x89, 0xc2, 0xd1, 0x80, 0xf2, 0x24], + [0x6b, 0x87, 0xf8, 0xfa, 0xed, 0x1c, 0xca, 0xc2], + [0x96, 0x21, 0x04, 0x9f, 0xfc, 0x4b, 0x16, 0xc2], + [0x23, 0xd6, 0xb1, 0x68, 0x93, 0x9c, 0x6e, 0xa1], + [0xfd, 0x14, 0x51, 0x8b, 0x9c, 0x16, 0xfb, 0x49], + [0x46, 0x4c, 0x07, 0xdf, 0xf8, 0x43, 0x31, 0x9f], + [0xb3, 0x86, 0xcc, 0x12, 0x24, 0xaf, 0xfd, 0xc6], + [0x8f, 0x09, 0x52, 0x0a, 0xd1, 0x49, 0xaf, 0x7e], + [0x9a, 0x2f, 0x29, 0x9d, 0x55, 0x13, 0xf3, 0x1c], + [0x12, 0x1f, 0xf4, 0xa2, 0xdd, 0x30, 0x4a, 0xc4], + [0xd0, 0x1e, 0xa7, 0x43, 0x89, 0xe9, 0xfa, 0x36], + [0xe6, 0xbc, 0xf0, 0x73, 0x4c, 0xb3, 0x8f, 0x31], + [0x80, 0xe9, 0xa7, 0x70, 0x36, 0xbf, 0x7a, 0xa2], + [0x75, 0x6d, 0x3c, 0x24, 0xdb, 0xc0, 0xbc, 0xb4], + [0x13, 0x15, 0xb7, 0xfd, 0x52, 0xd8, 0xf8, 0x23], + [0x08, 0x8a, 0x7d, 0xa6, 0x4d, 0x5f, 0x03, 0x8f], + [0x48, 0xf1, 0xe8, 0xb7, 0xe5, 0xd0, 0x9c, 0xd8], + [0xee, 0x44, 0xa6, 0xf7, 0xbc, 0xe6, 0xf4, 0xf6], + [0xf2, 0x37, 0x18, 0x0f, 0xd8, 0x9a, 0xc5, 0xae], + [0xe0, 0x94, 0x66, 0x4b, 0x15, 0xf6, 0xb2, 0xc3], + [0xa8, 0xb3, 0xbb, 0xb7, 0x62, 0x90, 0x19, 0x9d], ]; let k0 = 0x_07_06_05_04_03_02_01_00; @@ -143,71 +143,71 @@ fn test_siphash_1_3() { #[test] #[allow(unused_must_use)] fn test_siphash_2_4() { - let vecs : [[u8; 8]; 64] = [ - [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ], - [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ], - [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ], - [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ], - [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ], - [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ], - [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ], - [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ], - [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ], - [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ], - [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ], - [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ], - [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ], - [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ], - [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ], - [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ], - [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ], - [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ], - [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ], - [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ], - [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ], - [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ], - [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ], - [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ], - [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ], - [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ], - [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ], - [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ], - [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ], - [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ], - [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ], - [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ], - [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ], - [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ], - [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ], - [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ], - [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ], - [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ], - [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ], - [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ], - [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ], - [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ], - [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ], - [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ], - [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ], - [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ], - [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ], - [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ], - [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ], - [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ], - [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ], - [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ], - [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ], - [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ], - [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ], - [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ], - [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ], - [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ], - [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ], - [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ], - [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ], - [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ], - [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ], - [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ] + let vecs: [[u8; 8]; 64] = [ + [0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72], + [0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74], + [0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d], + [0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85], + [0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf], + [0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18], + [0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb], + [0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab], + [0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93], + [0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e], + [0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a], + [0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4], + [0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75], + [0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14], + [0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7], + [0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1], + [0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f], + [0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69], + [0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b], + [0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb], + [0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe], + [0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0], + [0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93], + [0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8], + [0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8], + [0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc], + [0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17], + [0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f], + [0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde], + [0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6], + [0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad], + [0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32], + [0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71], + [0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7], + [0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12], + [0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15], + [0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31], + [0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02], + [0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca], + [0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a], + [0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e], + [0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad], + [0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18], + [0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4], + [0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9], + [0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9], + [0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb], + [0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0], + [0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6], + [0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7], + [0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee], + [0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1], + [0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a], + [0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81], + [0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f], + [0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24], + [0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7], + [0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea], + [0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60], + [0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66], + [0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c], + [0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f], + [0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5], + [0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95], ]; let k0 = 0x_07_06_05_04_03_02_01_00; @@ -320,8 +320,7 @@ fn test_write_short_works() { h1.write_u8(0x01u8); let mut h2 = SipHasher::new(); h2.write(unsafe { - slice::from_raw_parts(&test_usize as *const _ as *const u8, - mem::size_of::()) + slice::from_raw_parts(&test_usize as *const _ as *const u8, mem::size_of::()) }); h2.write(b"bytes"); h2.write(b"string"); diff --git a/src/libcore/tests/intrinsics.rs b/src/libcore/tests/intrinsics.rs index 7544c13dee..fed7c4a5bf 100644 --- a/src/libcore/tests/intrinsics.rs +++ b/src/libcore/tests/intrinsics.rs @@ -2,7 +2,8 @@ use core::any::TypeId; #[test] fn test_typeid_sized_types() { - struct X; struct Y(u32); + struct X; + struct Y(u32); assert_eq!(TypeId::of::(), TypeId::of::()); assert_eq!(TypeId::of::(), TypeId::of::()); @@ -12,7 +13,8 @@ fn test_typeid_sized_types() { #[test] fn test_typeid_unsized_types() { trait Z {} - struct X(str); struct Y(dyn Z + 'static); + struct X(str); + struct Y(dyn Z + 'static); assert_eq!(TypeId::of::(), TypeId::of::()); assert_eq!(TypeId::of::(), TypeId::of::()); diff --git a/src/libcore/tests/manually_drop.rs b/src/libcore/tests/manually_drop.rs index 49a1c187ea..77a338daf7 100644 --- a/src/libcore/tests/manually_drop.rs +++ b/src/libcore/tests/manually_drop.rs @@ -13,7 +13,7 @@ fn smoke() { drop(x); // also test unsizing - let x : Box> = + let x: Box> = Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop])); drop(x); } diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index f5b241959f..59588d9778 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -96,7 +96,9 @@ fn test_transmute_copy() { #[test] fn test_transmute() { - trait Foo { fn dummy(&self) { } } + trait Foo { + fn dummy(&self) {} + } impl Foo for isize {} let a = box 100isize as Box; @@ -116,13 +118,13 @@ fn test_transmute() { fn test_discriminant_send_sync() { enum Regular { A, - B(i32) + B(i32), } enum NotSendSync { - A(*const i32) + A(*const i32), } - fn is_send_sync() { } + fn is_send_sync() {} is_send_sync::>(); is_send_sync::>(); diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 77e484601b..6c5d19845e 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -4,9 +4,7 @@ use std::mem::size_of; #[test] fn test_create_nonzero_instance() { - let _a = unsafe { - NonZeroU32::new_unchecked(21) - }; + let _a = unsafe { NonZeroU32::new_unchecked(21) }; } #[test] @@ -17,17 +15,15 @@ fn test_size_nonzero_in_option() { #[test] fn test_match_on_nonzero_option() { - let a = Some(unsafe { - NonZeroU32::new_unchecked(42) - }); + let a = Some(unsafe { NonZeroU32::new_unchecked(42) }); match a { Some(val) => assert_eq!(val.get(), 42), - None => panic!("unexpected None while matching on Some(NonZeroU32(_))") + None => panic!("unexpected None while matching on Some(NonZeroU32(_))"), } match unsafe { Some(NonZeroU32::new_unchecked(43)) } { Some(val) => assert_eq!(val.get(), 43), - None => panic!("unexpected None while matching on Some(NonZeroU32(_))") + None => panic!("unexpected None while matching on Some(NonZeroU32(_))"), } } @@ -45,7 +41,7 @@ fn test_match_option_vec() { let a = Some(vec![1, 2, 3, 4]); match a { Some(v) => assert_eq!(v, [1, 2, 3, 4]), - None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])") + None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])"), } } @@ -56,7 +52,7 @@ fn test_match_option_rc() { let five = Rc::new(5); match Some(five) { Some(r) => assert_eq!(*r, 5), - None => panic!("unexpected None while matching on Some(Rc::new(5))") + None => panic!("unexpected None while matching on Some(Rc::new(5))"), } } @@ -67,7 +63,7 @@ fn test_match_option_arc() { let five = Arc::new(5); match Some(five) { Some(a) => assert_eq!(*a, 5), - None => panic!("unexpected None while matching on Some(Arc::new(5))") + None => panic!("unexpected None while matching on Some(Arc::new(5))"), } } @@ -85,7 +81,7 @@ fn test_match_option_string() { let five = "Five".to_string(); match Some(five) { Some(s) => assert_eq!(s, "Five"), - None => panic!("unexpected None while matching on Some(String { ... })") + None => panic!("unexpected None while matching on Some(String { ... })"), } } @@ -100,7 +96,9 @@ mod atom { } macro_rules! atom { - ("foo") => { atom::FOO_ATOM } + ("foo") => { + atom::FOO_ATOM + }; } #[test] @@ -108,7 +106,7 @@ fn test_match_nonzero_const_pattern() { match atom!("foo") { // Using as a pattern is supported by the compiler: atom!("foo") => {} - _ => panic!("Expected the const item as a pattern to match.") + _ => panic!("Expected the const item as a pattern to match."), } } @@ -129,10 +127,7 @@ fn test_from_signed_nonzero() { #[test] fn test_from_str() { assert_eq!("123".parse::(), Ok(NonZeroU8::new(123).unwrap())); - assert_eq!( - "0".parse::().err().map(|e| e.kind().clone()), - Some(IntErrorKind::Zero) - ); + assert_eq!("0".parse::().err().map(|e| e.kind().clone()), Some(IntErrorKind::Zero)); assert_eq!( "-1".parse::().err().map(|e| e.kind().clone()), Some(IntErrorKind::InvalidDigit) diff --git a/src/libcore/tests/num/bignum.rs b/src/libcore/tests/num/bignum.rs index b9e15ec5c0..1457064cc8 100644 --- a/src/libcore/tests/num/bignum.rs +++ b/src/libcore/tests/num/bignum.rs @@ -1,4 +1,3 @@ -use std::prelude::v1::*; use core::num::bignum::tests::Big8x3 as Big; #[test] @@ -71,7 +70,7 @@ fn test_sub_underflow_2() { fn test_mul_small() { assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35)); assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01)); - assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff)); + assert_eq!(*Big::from_u64(0xffffff / 13).mul_small(13), Big::from_u64(0xffffff)); } #[test] @@ -135,7 +134,7 @@ fn test_mul_digits() { assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2)); assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3)); assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e)); - assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff)); + assert_eq!(*Big::from_u64(0xffffff / 13).mul_digits(&[13]), Big::from_u64(0xffffff)); assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff)); } @@ -157,10 +156,14 @@ fn test_div_rem_small() { assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0)); assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15)); assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3)); - assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)), - (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8)); - assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)), - (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8)); + assert_eq!( + as_val(Big::from_u64(0xffffff).div_rem_small(123)), + (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8) + ); + assert_eq!( + as_val(Big::from_u64(0x10000).div_rem_small(123)), + (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8) + ); } #[test] diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index 46eacb4200..6bb348fd75 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -1,6 +1,6 @@ #![allow(overflowing_literals)] -use std::{i64, f32, f64}; +use std::{f32, f64, i64}; mod parse; mod rawfp; @@ -9,7 +9,7 @@ mod rawfp; // to be correct) and see if those strings are parsed back to the value of the literal. // Requires a *polymorphic literal*, i.e., one that can serve as f64 as well as f32. macro_rules! test_literal { - ($x: expr) => ({ + ($x: expr) => {{ let x32: f32 = $x; let x64: f64 = $x; let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)]; @@ -20,7 +20,7 @@ macro_rules! test_literal { assert_eq!(neg_input.parse(), Ok(-x64)); assert_eq!(neg_input.parse(), Ok(-x32)); } - }) + }}; } #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 @@ -31,7 +31,11 @@ fn ordinary() { test_literal!(0.1); test_literal!(12345.); test_literal!(0.9999999); - #[cfg(not(miri))] // Miri is too slow + + if cfg!(miri) { // Miri is too slow + return; + } + test_literal!(2.2250738585072014e-308); } @@ -53,7 +57,7 @@ fn large() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn subnormals() { test_literal!(5e-324); test_literal!(91e-324); @@ -65,7 +69,7 @@ fn subnormals() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn infinity() { test_literal!(1e400); test_literal!(1e309); @@ -77,9 +81,12 @@ fn infinity() { fn zero() { test_literal!(0.0); test_literal!(1e-325); - #[cfg(not(miri))] // Miri is too slow + + if cfg!(miri) { // Miri is too slow + return; + } + test_literal!(1e-326); - #[cfg(not(miri))] // Miri is too slow test_literal!(1e-500); } diff --git a/src/libcore/tests/num/dec2flt/parse.rs b/src/libcore/tests/num/dec2flt/parse.rs index 1eac484119..bb7e51d300 100644 --- a/src/libcore/tests/num/dec2flt/parse.rs +++ b/src/libcore/tests/num/dec2flt/parse.rs @@ -1,5 +1,5 @@ -use core::num::dec2flt::parse::{Decimal, parse_decimal}; -use core::num::dec2flt::parse::ParseResult::{Valid, Invalid}; +use core::num::dec2flt::parse::ParseResult::{Invalid, Valid}; +use core::num::dec2flt::parse::{parse_decimal, Decimal}; #[test] fn missing_pieces() { diff --git a/src/libcore/tests/num/dec2flt/rawfp.rs b/src/libcore/tests/num/dec2flt/rawfp.rs index 747c1bfa3f..665fb6b9ef 100644 --- a/src/libcore/tests/num/dec2flt/rawfp.rs +++ b/src/libcore/tests/num/dec2flt/rawfp.rs @@ -1,8 +1,8 @@ +use core::num::dec2flt::rawfp::RawFloat; +use core::num::dec2flt::rawfp::{fp_to_float, next_float, prev_float, round_normal}; +use core::num::diy_float::Fp; use std::f32; use std::f64; -use core::num::diy_float::Fp; -use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal}; -use core::num::dec2flt::rawfp::RawFloat; fn integer_decode(f: f64) -> (u64, i16, i8) { RawFloat::integer_decode(f) @@ -53,16 +53,23 @@ fn integers_to_f64() { assert_eq!(fp_to_float::(Fp { f: 4, e: -3 }), 0.5); } -const SOME_FLOATS: [f64; 9] = - [0.1f64, 33.568, 42.1e-5, 777.0e9, 1.1111, 0.347997, - 9843579834.35892, 12456.0e-150, 54389573.0e-150]; - +const SOME_FLOATS: [f64; 9] = [ + 0.1f64, + 33.568, + 42.1e-5, + 777.0e9, + 1.1111, + 0.347997, + 9843579834.35892, + 12456.0e-150, + 54389573.0e-150, +]; #[test] fn human_f64_roundtrip() { for &x in &SOME_FLOATS { let (f, e, _) = integer_decode(x); - let fp = Fp { f: f, e: e}; + let fp = Fp { f: f, e: e }; assert_eq!(fp_to_float::(fp), x); } } diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs index c51451708f..8ee06d895c 100644 --- a/src/libcore/tests/num/flt2dec/estimator.rs +++ b/src/libcore/tests/num/flt2dec/estimator.rs @@ -3,14 +3,24 @@ use core::num::flt2dec::estimator::*; #[test] fn test_estimate_scaling_factor() { macro_rules! assert_almost_eq { - ($actual:expr, $expected:expr) => ({ + ($actual:expr, $expected:expr) => {{ let actual = $actual; let expected = $expected; - println!("{} - {} = {} - {} = {}", stringify!($expected), stringify!($actual), - expected, actual, expected - actual); - assert!(expected == actual || expected == actual + 1, - "expected {}, actual {}", expected, actual); - }) + println!( + "{} - {} = {} - {} = {}", + stringify!($expected), + stringify!($actual), + expected, + actual, + expected - actual + ); + assert!( + expected == actual || expected == actual + 1, + "expected {}, actual {}", + expected, + actual + ); + }}; } assert_almost_eq!(estimate_scaling_factor(1, 0), 0); diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs index c41d35efce..2f94ea2fc4 100644 --- a/src/libcore/tests/num/flt2dec/mod.rs +++ b/src/libcore/tests/num/flt2dec/mod.rs @@ -1,4 +1,3 @@ -use std::prelude::v1::*; use std::{str, i16, f32, f64, fmt}; use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; @@ -85,6 +84,8 @@ fn ldexp_f64(a: f64, b: i32) -> f64 { extern { fn ldexp(x: f64, n: i32) -> f64; } + // SAFETY: assuming a correct `ldexp` has been supplied, the given arguments cannot possibly + // cause undefined behavior unsafe { ldexp(a, b) } } @@ -255,7 +256,6 @@ pub fn f32_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) check_shortest!(f(minf32) => b"1", -44); } -#[cfg(not(miri))] // Miri is too slow pub fn f32_exact_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { let minf32 = ldexp_f32(1.0, -149); @@ -361,7 +361,6 @@ pub fn f64_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) check_shortest!(f(minf64) => b"5", -323); } -#[cfg(not(miri))] // Miri is too slow pub fn f64_exact_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { let minf64 = ldexp_f64(1.0, -1074); diff --git a/src/libcore/tests/num/flt2dec/random.rs b/src/libcore/tests/num/flt2dec/random.rs index d954379339..ecdfc4b30a 100644 --- a/src/libcore/tests/num/flt2dec/random.rs +++ b/src/libcore/tests/num/flt2dec/random.rs @@ -3,27 +3,28 @@ use std::i16; use std::str; -use core::num::flt2dec::MAX_SIG_DIGITS; use core::num::flt2dec::strategy::grisu::format_exact_opt; use core::num::flt2dec::strategy::grisu::format_shortest_opt; -use core::num::flt2dec::{decode, DecodableFloat, FullDecoded, Decoded}; +use core::num::flt2dec::MAX_SIG_DIGITS; +use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded}; -use rand::SeedableRng; -use rand::rngs::StdRng; use rand::distributions::{Distribution, Uniform}; +use rand::rngs::StdRng; +use rand::SeedableRng; pub fn decode_finite(v: T) -> Decoded { match decode(v).1 { FullDecoded::Finite(decoded) => decoded, - full_decoded => panic!("expected finite, got {:?} instead", full_decoded) + full_decoded => panic!("expected finite, got {:?} instead", full_decoded), } } - fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V) -> (usize, usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), - V: FnMut(usize) -> Decoded { +where + F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), + V: FnMut(usize) -> Decoded, +{ assert!(k <= 1024); let mut npassed = 0; // f(x) = Some(g(x)) @@ -31,8 +32,14 @@ fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V for i in 0..n { if (i & 0xfffff) == 0 { - println!("in progress, {:x}/{:x} (ignored={} passed={} failed={})", - i, n, nignored, npassed, i - nignored - npassed); + println!( + "in progress, {:x}/{:x} (ignored={} passed={} failed={})", + i, + n, + nignored, + npassed, + i - nignored - npassed + ); } let decoded = v(i); @@ -43,27 +50,47 @@ fn iterate(func: &str, k: usize, n: usize, mut f: F, mut g: G, mut v: V if e1 == e2 && &buf1[..len1] == &buf2[..len2] { npassed += 1; } else { - println!("equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}", - i, n, decoded, str::from_utf8(&buf1[..len1]).unwrap(), e1, - str::from_utf8(&buf2[..len2]).unwrap(), e2); + println!( + "equivalence test failed, {:x}/{:x}: {:?} f(i)={}e{} g(i)={}e{}", + i, + n, + decoded, + str::from_utf8(&buf1[..len1]).unwrap(), + e1, + str::from_utf8(&buf2[..len2]).unwrap(), + e2 + ); } } else { nignored += 1; } } - println!("{}({}): done, ignored={} passed={} failed={}", - func, k, nignored, npassed, n - nignored - npassed); - assert!(nignored + npassed == n, - "{}({}): {} out of {} values returns an incorrect value!", - func, k, n - nignored - npassed, n); + println!( + "{}({}): done, ignored={} passed={} failed={}", + func, + k, + nignored, + npassed, + n - nignored - npassed + ); + assert!( + nignored + npassed == n, + "{}({}): {} out of {} values returns an incorrect value!", + func, + k, + n - nignored - npassed, + n + ); (npassed, nignored) } pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +where + F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), +{ if cfg!(target_os = "emscripten") { - return // using rng pulls in i128 support, which doesn't work + return; // using rng pulls in i128 support, which doesn't work } let mut rng = StdRng::from_entropy(); let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000); @@ -74,10 +101,12 @@ pub fn f32_random_equivalence_test(f: F, g: G, k: usize, n: usize) } pub fn f64_random_equivalence_test(f: F, g: G, k: usize, n: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +where + F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), +{ if cfg!(target_os = "emscripten") { - return // using rng pulls in i128 support, which doesn't work + return; // using rng pulls in i128 support, which doesn't work } let mut rng = StdRng::from_entropy(); let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); @@ -88,8 +117,10 @@ pub fn f64_random_equivalence_test(f: F, g: G, k: usize, n: usize) } pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) - where F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, - G: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +where + F: FnMut(&Decoded, &mut [u8]) -> Option<(usize, i16)>, + G: FnMut(&Decoded, &mut [u8]) -> (usize, i16), +{ // we have only 2^23 * (2^8 - 1) - 1 = 2,139,095,039 positive finite f32 values, // so why not simply testing all of them? // @@ -97,12 +128,11 @@ pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) // but with `-C opt-level=3 -C lto` this only takes about an hour or so. // iterate from 0x0000_0001 to 0x7f7f_ffff, i.e., all finite ranges - let (npassed, nignored) = iterate("f32_exhaustive_equivalence_test", - k, 0x7f7f_ffff, f, g, |i: usize| { - - let x = f32::from_bits(i as u32 + 1); - decode_finite(x) - }); + let (npassed, nignored) = + iterate("f32_exhaustive_equivalence_test", k, 0x7f7f_ffff, f, g, |i: usize| { + let x = f32::from_bits(i as u32 + 1); + decode_finite(x) + }); assert_eq!((npassed, nignored), (2121451881, 17643158)); } @@ -118,7 +148,8 @@ fn shortest_random_equivalence_test() { f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, N); } -#[test] #[ignore] // it is too expensive +#[test] +#[ignore] // it is too expensive fn shortest_f32_exhaustive_equivalence_test() { // it is hard to directly test the optimality of the output, but we can at least test if // two different algorithms agree to each other. @@ -131,13 +162,13 @@ fn shortest_f32_exhaustive_equivalence_test() { f32_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS); } -#[test] #[ignore] // it is too expensive +#[test] +#[ignore] // it is too expensive fn shortest_f64_hard_random_equivalence_test() { // this again probably has to use appropriate rustc flags. use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f64_random_equivalence_test(format_shortest_opt, fallback, - MAX_SIG_DIGITS, 100_000_000); + f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 100_000_000); } #[test] @@ -149,8 +180,12 @@ fn exact_f32_random_equivalence_test() { const N: usize = 3; for k in 1..21 { - f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, N); + f32_random_equivalence_test( + |d, buf| format_exact_opt(d, buf, i16::MIN), + |d, buf| fallback(d, buf, i16::MIN), + k, + N, + ); } } @@ -163,7 +198,11 @@ fn exact_f64_random_equivalence_test() { const N: usize = 3; for k in 1..21 { - f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, N); + f64_random_equivalence_test( + |d, buf| format_exact_opt(d, buf, i16::MIN), + |d, buf| fallback(d, buf, i16::MIN), + k, + N, + ); } } diff --git a/src/libcore/tests/num/flt2dec/strategy/dragon.rs b/src/libcore/tests/num/flt2dec/strategy/dragon.rs index dc4d78bfae..3d985c6796 100644 --- a/src/libcore/tests/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/tests/num/flt2dec/strategy/dragon.rs @@ -1,4 +1,3 @@ -use std::prelude::v1::*; use super::super::*; use core::num::bignum::Big32x40 as Big; use core::num::flt2dec::strategy::dragon::*; @@ -23,7 +22,7 @@ fn shortest_sanity_test() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn exact_sanity_test() { // This test ends up running what I can only assume is some corner-ish case // of the `exp2` library function, defined in whatever C runtime we're diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs index f8bdddfe2e..ff8373c645 100644 --- a/src/libcore/tests/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs @@ -6,12 +6,18 @@ fn test_cached_power() { assert_eq!(CACHED_POW10.first().unwrap().1, CACHED_POW10_FIRST_E); assert_eq!(CACHED_POW10.last().unwrap().1, CACHED_POW10_LAST_E); - for e in -1137..961 { // full range for f64 + for e in -1137..961 { + // full range for f64 let low = ALPHA - e - 64; let high = GAMMA - e - 64; let (_k, cached) = cached_power(low, high); - assert!(low <= cached.e && cached.e <= high, - "cached_power({}, {}) = {:?} is incorrect", low, high, cached); + assert!( + low <= cached.e && cached.e <= high, + "cached_power({}, {}) = {:?} is incorrect", + low, + high, + cached + ); } } @@ -26,7 +32,6 @@ fn test_max_pow10_no_more_than() { } } - #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn shortest_sanity_test() { @@ -36,7 +41,7 @@ fn shortest_sanity_test() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn exact_sanity_test() { // See comments in dragon.rs's exact_sanity_test for why this test is // ignored on MSVC diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 0475aeb96a..4a44b5f24b 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -1,240 +1,241 @@ -macro_rules! int_module { ($T:ident, $T_i:ident) => ( -#[cfg(test)] -mod tests { - use core::$T_i::*; - use core::isize; - use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr}; - use core::mem; - - use crate::num; - - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert_eq!(MIN + MAX + 1, 0); - } - - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); - } - - #[test] - fn test_rem_euclid() { - assert_eq!((-1 as $T).rem_euclid(MIN), MAX); - } - - #[test] - pub fn test_abs() { - assert_eq!((1 as $T).abs(), 1 as $T); - assert_eq!((0 as $T).abs(), 0 as $T); - assert_eq!((-1 as $T).abs(), 1 as $T); - } - - #[test] - fn test_signum() { - assert_eq!((1 as $T).signum(), 1 as $T); - assert_eq!((0 as $T).signum(), 0 as $T); - assert_eq!((-0 as $T).signum(), 0 as $T); - assert_eq!((-1 as $T).signum(), -1 as $T); - } - - #[test] - fn test_is_positive() { - assert!((1 as $T).is_positive()); - assert!(!(0 as $T).is_positive()); - assert!(!(-0 as $T).is_positive()); - assert!(!(-1 as $T).is_positive()); - } - - #[test] - fn test_is_negative() { - assert!(!(1 as $T).is_negative()); - assert!(!(0 as $T).is_negative()); - assert!(!(-0 as $T).is_negative()); - assert!((-1 as $T).is_negative()); - } - - #[test] - fn test_bitwise_operators() { - assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T)); - assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T)); - assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T)); - assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1)); - assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1)); - assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not()); - } - - const A: $T = 0b0101100; - const B: $T = 0b0100001; - const C: $T = 0b1111001; - - const _0: $T = 0; - const _1: $T = !0; - - #[test] - fn test_count_ones() { - assert_eq!(A.count_ones(), 3); - assert_eq!(B.count_ones(), 2); - assert_eq!(C.count_ones(), 5); - } - - #[test] - fn test_count_zeros() { - let bits = mem::size_of::<$T>() * 8; - assert_eq!(A.count_zeros(), bits as u32 - 3); - assert_eq!(B.count_zeros(), bits as u32 - 2); - assert_eq!(C.count_zeros(), bits as u32 - 5); - } - - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); - - // Rotating these should make no difference - // - // We test using 124 bits because to ensure that overlong bit shifts do - // not cause undefined behaviour. See #10183. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - - // Rotating by 0 should have no effect - assert_eq!(A.rotate_left(0), A); - assert_eq!(B.rotate_left(0), B); - assert_eq!(C.rotate_left(0), C); - // Rotating by a multiple of word size should also have no effect - assert_eq!(A.rotate_left(64), A); - assert_eq!(B.rotate_left(64), B); - assert_eq!(C.rotate_left(64), C); - } - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_le() { - assert_eq!($T::from_le(A.to_le()), A); - assert_eq!($T::from_le(B.to_le()), B); - assert_eq!($T::from_le(C.to_le()), C); - assert_eq!($T::from_le(_0), _0); - assert_eq!($T::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } - - #[test] - fn test_be() { - assert_eq!($T::from_be(A.to_be()), A); - assert_eq!($T::from_be(B.to_be()), B); - assert_eq!($T::from_be(C.to_be()), C); - assert_eq!($T::from_be(_0), _0); - assert_eq!($T::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } - - #[test] - fn test_signed_checked_div() { - assert_eq!((10 as $T).checked_div(2), Some(5)); - assert_eq!((5 as $T).checked_div(0), None); - assert_eq!(isize::MIN.checked_div(-1), None); - } - - #[test] - fn test_saturating_abs() { - assert_eq!((0 as $T).saturating_abs(), 0); - assert_eq!((123 as $T).saturating_abs(), 123); - assert_eq!((-123 as $T).saturating_abs(), 123); - assert_eq!((MAX - 2).saturating_abs(), MAX - 2); - assert_eq!((MAX - 1).saturating_abs(), MAX - 1); - assert_eq!(MAX.saturating_abs(), MAX); - assert_eq!((MIN + 2).saturating_abs(), MAX - 1); - assert_eq!((MIN + 1).saturating_abs(), MAX); - assert_eq!(MIN.saturating_abs(), MAX); - } - - #[test] - fn test_saturating_neg() { - assert_eq!((0 as $T).saturating_neg(), 0); - assert_eq!((123 as $T).saturating_neg(), -123); - assert_eq!((-123 as $T).saturating_neg(), 123); - assert_eq!((MAX - 2).saturating_neg(), MIN + 3); - assert_eq!((MAX - 1).saturating_neg(), MIN + 2); - assert_eq!(MAX.saturating_neg(), MIN + 1); - assert_eq!((MIN + 2).saturating_neg(), MAX - 1); - assert_eq!((MIN + 1).saturating_neg(), MAX); - assert_eq!(MIN.saturating_neg(), MAX); - } - - #[test] - fn test_from_str() { - fn from_str(t: &str) -> Option { - ::std::str::FromStr::from_str(t).ok() +macro_rules! int_module { + ($T:ident, $T_i:ident) => { + #[cfg(test)] + mod tests { + use core::isize; + use core::mem; + use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + use core::$T_i::*; + + use crate::num; + + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert_eq!(MIN + MAX + 1, 0); + } + + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } + + #[test] + fn test_rem_euclid() { + assert_eq!((-1 as $T).rem_euclid(MIN), MAX); + } + + #[test] + pub fn test_abs() { + assert_eq!((1 as $T).abs(), 1 as $T); + assert_eq!((0 as $T).abs(), 0 as $T); + assert_eq!((-1 as $T).abs(), 1 as $T); + } + + #[test] + fn test_signum() { + assert_eq!((1 as $T).signum(), 1 as $T); + assert_eq!((0 as $T).signum(), 0 as $T); + assert_eq!((-0 as $T).signum(), 0 as $T); + assert_eq!((-1 as $T).signum(), -1 as $T); + } + + #[test] + fn test_is_positive() { + assert!((1 as $T).is_positive()); + assert!(!(0 as $T).is_positive()); + assert!(!(-0 as $T).is_positive()); + assert!(!(-1 as $T).is_positive()); + } + + #[test] + fn test_is_negative() { + assert!(!(1 as $T).is_negative()); + assert!(!(0 as $T).is_negative()); + assert!(!(-0 as $T).is_negative()); + assert!((-1 as $T).is_negative()); + } + + #[test] + fn test_bitwise_operators() { + assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T)); + assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T)); + assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T)); + assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1)); + assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1)); + assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not()); + } + + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; + + const _0: $T = 0; + const _1: $T = !0; + + #[test] + fn test_count_ones() { + assert_eq!(A.count_ones(), 3); + assert_eq!(B.count_ones(), 2); + assert_eq!(C.count_ones(), 5); + } + + #[test] + fn test_count_zeros() { + let bits = mem::size_of::<$T>() * 8; + assert_eq!(A.count_zeros(), bits as u32 - 3); + assert_eq!(B.count_zeros(), bits as u32 - 2); + assert_eq!(C.count_zeros(), bits as u32 - 5); + } + + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // Rotating these should make no difference + // + // We test using 124 bits because to ensure that overlong bit shifts do + // not cause undefined behaviour. See #10183. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + + // Rotating by 0 should have no effect + assert_eq!(A.rotate_left(0), A); + assert_eq!(B.rotate_left(0), B); + assert_eq!(C.rotate_left(0), C); + // Rotating by a multiple of word size should also have no effect + assert_eq!(A.rotate_left(64), A); + assert_eq!(B.rotate_left(64), B); + assert_eq!(C.rotate_left(64), C); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_le() { + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } + + #[test] + fn test_be() { + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } + + #[test] + fn test_signed_checked_div() { + assert_eq!((10 as $T).checked_div(2), Some(5)); + assert_eq!((5 as $T).checked_div(0), None); + assert_eq!(isize::MIN.checked_div(-1), None); + } + + #[test] + fn test_saturating_abs() { + assert_eq!((0 as $T).saturating_abs(), 0); + assert_eq!((123 as $T).saturating_abs(), 123); + assert_eq!((-123 as $T).saturating_abs(), 123); + assert_eq!((MAX - 2).saturating_abs(), MAX - 2); + assert_eq!((MAX - 1).saturating_abs(), MAX - 1); + assert_eq!(MAX.saturating_abs(), MAX); + assert_eq!((MIN + 2).saturating_abs(), MAX - 1); + assert_eq!((MIN + 1).saturating_abs(), MAX); + assert_eq!(MIN.saturating_abs(), MAX); + } + + #[test] + fn test_saturating_neg() { + assert_eq!((0 as $T).saturating_neg(), 0); + assert_eq!((123 as $T).saturating_neg(), -123); + assert_eq!((-123 as $T).saturating_neg(), 123); + assert_eq!((MAX - 2).saturating_neg(), MIN + 3); + assert_eq!((MAX - 1).saturating_neg(), MIN + 2); + assert_eq!(MAX.saturating_neg(), MIN + 1); + assert_eq!((MIN + 2).saturating_neg(), MAX - 1); + assert_eq!((MIN + 1).saturating_neg(), MAX); + assert_eq!(MIN.saturating_neg(), MAX); + } + + #[test] + fn test_from_str() { + fn from_str(t: &str) -> Option { + ::std::str::FromStr::from_str(t).ok() + } + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::("123456789"), Some(123456789 as i32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); + assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); + assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); + assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); + assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } + + #[test] + fn test_from_str_radix() { + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32)); + assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); + assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T)); + assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); + assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T)); + assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); + assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); + assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); + assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T)); + assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); + + assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); + assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); + } + + #[test] + fn test_pow() { + let mut r = 2 as $T; + + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(0), 1 as $T); + r = -2 as $T; + assert_eq!(r.pow(2), 4 as $T); + assert_eq!(r.pow(3), -8 as $T); + } } - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::("123456789"), Some(123456789 as i32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); - assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); - assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); - assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); - assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } - - #[test] - fn test_from_str_radix() { - assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32)); - assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); - assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); - assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); - assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T)); - - assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T)); - assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); - assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T)); - assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); - assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); - assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); - assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T)); - assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); - - assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); - assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); - } - - #[test] - fn test_pow() { - let mut r = 2 as $T; - - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(0), 1 as $T); - r = -2 as $T; - assert_eq!(r.pow(2), 4 as $T); - assert_eq!(r.pow(3), -8 as $T); - } + }; } - -)} diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs index 04ed14f3d0..f94b2f56bb 100644 --- a/src/libcore/tests/num/uint_macros.rs +++ b/src/libcore/tests/num/uint_macros.rs @@ -1,160 +1,162 @@ -macro_rules! uint_module { ($T:ident, $T_i:ident) => ( -#[cfg(test)] -mod tests { - use core::$T_i::*; - use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not}; - use std::str::FromStr; - use std::mem; - - use crate::num; - - #[test] - fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert!((MIN + MAX).wrapping_add(1) == 0); - } - - #[test] - fn test_num() { - num::test_num(10 as $T, 2 as $T); - } - - #[test] - fn test_bitwise_operators() { - assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T)); - assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T)); - assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T)); - assert!(0b1110 as $T == (0b0111 as $T).shl(1)); - assert!(0b0111 as $T == (0b1110 as $T).shr(1)); - assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); - } - - const A: $T = 0b0101100; - const B: $T = 0b0100001; - const C: $T = 0b1111001; - - const _0: $T = 0; - const _1: $T = !0; - - #[test] - fn test_count_ones() { - assert!(A.count_ones() == 3); - assert!(B.count_ones() == 2); - assert!(C.count_ones() == 5); - } - - #[test] - fn test_count_zeros() { - let bits = mem::size_of::<$T>() * 8; - assert!(A.count_zeros() == bits as u32 - 3); - assert!(B.count_zeros() == bits as u32 - 2); - assert!(C.count_zeros() == bits as u32 - 5); - } - - #[test] - fn test_rotate() { - assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); - - // Rotating these should make no difference - // - // We test using 124 bits because to ensure that overlong bit shifts do - // not cause undefined behaviour. See #10183. - assert_eq!(_0.rotate_left(124), _0); - assert_eq!(_1.rotate_left(124), _1); - assert_eq!(_0.rotate_right(124), _0); - assert_eq!(_1.rotate_right(124), _1); - - // Rotating by 0 should have no effect - assert_eq!(A.rotate_left(0), A); - assert_eq!(B.rotate_left(0), B); - assert_eq!(C.rotate_left(0), C); - // Rotating by a multiple of word size should also have no effect - assert_eq!(A.rotate_left(64), A); - assert_eq!(B.rotate_left(64), B); - assert_eq!(C.rotate_left(64), C); - } - - #[test] - fn test_swap_bytes() { - assert_eq!(A.swap_bytes().swap_bytes(), A); - assert_eq!(B.swap_bytes().swap_bytes(), B); - assert_eq!(C.swap_bytes().swap_bytes(), C); - - // Swapping these should make no difference - assert_eq!(_0.swap_bytes(), _0); - assert_eq!(_1.swap_bytes(), _1); - } - - #[test] - fn test_reverse_bits() { - assert_eq!(A.reverse_bits().reverse_bits(), A); - assert_eq!(B.reverse_bits().reverse_bits(), B); - assert_eq!(C.reverse_bits().reverse_bits(), C); - - // Swapping these should make no difference - assert_eq!(_0.reverse_bits(), _0); - assert_eq!(_1.reverse_bits(), _1); - } - - #[test] - fn test_le() { - assert_eq!($T::from_le(A.to_le()), A); - assert_eq!($T::from_le(B.to_le()), B); - assert_eq!($T::from_le(C.to_le()), C); - assert_eq!($T::from_le(_0), _0); - assert_eq!($T::from_le(_1), _1); - assert_eq!(_0.to_le(), _0); - assert_eq!(_1.to_le(), _1); - } - - #[test] - fn test_be() { - assert_eq!($T::from_be(A.to_be()), A); - assert_eq!($T::from_be(B.to_be()), B); - assert_eq!($T::from_be(C.to_be()), C); - assert_eq!($T::from_be(_0), _0); - assert_eq!($T::from_be(_1), _1); - assert_eq!(_0.to_be(), _0); - assert_eq!(_1.to_be(), _1); - } - - #[test] - fn test_unsigned_checked_div() { - assert!((10 as $T).checked_div(2) == Some(5)); - assert!((5 as $T).checked_div(0) == None); - } - - fn from_str(t: &str) -> Option { - FromStr::from_str(t).ok() - } - - #[test] - pub fn test_from_str() { - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::("123456789"), Some(123456789 as u32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } - - #[test] - pub fn test_parse_bytes() { - assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16)); - assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); - assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); - - assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); - assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); - } +macro_rules! uint_module { + ($T:ident, $T_i:ident) => { + #[cfg(test)] + mod tests { + use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; + use core::$T_i::*; + use std::mem; + use std::str::FromStr; + + use crate::num; + + #[test] + fn test_overflows() { + assert!(MAX > 0); + assert!(MIN <= 0); + assert!((MIN + MAX).wrapping_add(1) == 0); + } + + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } + + #[test] + fn test_bitwise_operators() { + assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T)); + assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T)); + assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T)); + assert!(0b1110 as $T == (0b0111 as $T).shl(1)); + assert!(0b0111 as $T == (0b1110 as $T).shr(1)); + assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); + } + + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; + + const _0: $T = 0; + const _1: $T = !0; + + #[test] + fn test_count_ones() { + assert!(A.count_ones() == 3); + assert!(B.count_ones() == 2); + assert!(C.count_ones() == 5); + } + + #[test] + fn test_count_zeros() { + let bits = mem::size_of::<$T>() * 8; + assert!(A.count_zeros() == bits as u32 - 3); + assert!(B.count_zeros() == bits as u32 - 2); + assert!(C.count_zeros() == bits as u32 - 5); + } + + #[test] + fn test_rotate() { + assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + + // Rotating these should make no difference + // + // We test using 124 bits because to ensure that overlong bit shifts do + // not cause undefined behaviour. See #10183. + assert_eq!(_0.rotate_left(124), _0); + assert_eq!(_1.rotate_left(124), _1); + assert_eq!(_0.rotate_right(124), _0); + assert_eq!(_1.rotate_right(124), _1); + + // Rotating by 0 should have no effect + assert_eq!(A.rotate_left(0), A); + assert_eq!(B.rotate_left(0), B); + assert_eq!(C.rotate_left(0), C); + // Rotating by a multiple of word size should also have no effect + assert_eq!(A.rotate_left(64), A); + assert_eq!(B.rotate_left(64), B); + assert_eq!(C.rotate_left(64), C); + } + + #[test] + fn test_swap_bytes() { + assert_eq!(A.swap_bytes().swap_bytes(), A); + assert_eq!(B.swap_bytes().swap_bytes(), B); + assert_eq!(C.swap_bytes().swap_bytes(), C); + + // Swapping these should make no difference + assert_eq!(_0.swap_bytes(), _0); + assert_eq!(_1.swap_bytes(), _1); + } + + #[test] + fn test_reverse_bits() { + assert_eq!(A.reverse_bits().reverse_bits(), A); + assert_eq!(B.reverse_bits().reverse_bits(), B); + assert_eq!(C.reverse_bits().reverse_bits(), C); + + // Swapping these should make no difference + assert_eq!(_0.reverse_bits(), _0); + assert_eq!(_1.reverse_bits(), _1); + } + + #[test] + fn test_le() { + assert_eq!($T::from_le(A.to_le()), A); + assert_eq!($T::from_le(B.to_le()), B); + assert_eq!($T::from_le(C.to_le()), C); + assert_eq!($T::from_le(_0), _0); + assert_eq!($T::from_le(_1), _1); + assert_eq!(_0.to_le(), _0); + assert_eq!(_1.to_le(), _1); + } + + #[test] + fn test_be() { + assert_eq!($T::from_be(A.to_be()), A); + assert_eq!($T::from_be(B.to_be()), B); + assert_eq!($T::from_be(C.to_be()), C); + assert_eq!($T::from_be(_0), _0); + assert_eq!($T::from_be(_1), _1); + assert_eq!(_0.to_be(), _0); + assert_eq!(_1.to_be(), _1); + } + + #[test] + fn test_unsigned_checked_div() { + assert!((10 as $T).checked_div(2) == Some(5)); + assert!((5 as $T).checked_div(0) == None); + } + + fn from_str(t: &str) -> Option { + FromStr::from_str(t).ok() + } + + #[test] + pub fn test_from_str() { + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::("123456789"), Some(123456789 as u32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } + + #[test] + pub fn test_parse_bytes() { + assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq!(u16::from_str_radix("123", 16), Ok(291 as u16)); + assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); + assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T)); + + assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>); + assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>); + } + } + }; } -)} diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs index 48755ae4c1..43eb498d26 100644 --- a/src/libcore/tests/ops.rs +++ b/src/libcore/tests/ops.rs @@ -1,4 +1,4 @@ -use core::ops::{Bound, Range, RangeFull, RangeFrom, RangeTo, RangeInclusive}; +use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo}; // Test the Range structs without the syntactic sugar. @@ -59,28 +59,27 @@ fn test_range_inclusive() { assert_eq!(r.next(), None); } - #[test] fn test_range_is_empty() { use core::f32::*; - assert!(!(0.0 .. 10.0).is_empty()); - assert!( (-0.0 .. 0.0).is_empty()); - assert!( (10.0 .. 0.0).is_empty()); + assert!(!(0.0..10.0).is_empty()); + assert!((-0.0..0.0).is_empty()); + assert!((10.0..0.0).is_empty()); - assert!(!(NEG_INFINITY .. INFINITY).is_empty()); - assert!( (EPSILON .. NAN).is_empty()); - assert!( (NAN .. EPSILON).is_empty()); - assert!( (NAN .. NAN).is_empty()); + assert!(!(NEG_INFINITY..INFINITY).is_empty()); + assert!((EPSILON..NAN).is_empty()); + assert!((NAN..EPSILON).is_empty()); + assert!((NAN..NAN).is_empty()); - assert!(!(0.0 ..= 10.0).is_empty()); - assert!(!(-0.0 ..= 0.0).is_empty()); - assert!( (10.0 ..= 0.0).is_empty()); + assert!(!(0.0..=10.0).is_empty()); + assert!(!(-0.0..=0.0).is_empty()); + assert!((10.0..=0.0).is_empty()); - assert!(!(NEG_INFINITY ..= INFINITY).is_empty()); - assert!( (EPSILON ..= NAN).is_empty()); - assert!( (NAN ..= EPSILON).is_empty()); - assert!( (NAN ..= NAN).is_empty()); + assert!(!(NEG_INFINITY..=INFINITY).is_empty()); + assert!((EPSILON..=NAN).is_empty()); + assert!((NAN..=EPSILON).is_empty()); + assert!((NAN..=NAN).is_empty()); } #[test] diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index ff43fc49f7..fa308160fc 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -1,8 +1,8 @@ -use core::option::*; -use core::mem; -use core::clone::Clone; use core::array::FixedSizeArray; +use core::clone::Clone; +use core::mem; use core::ops::DerefMut; +use core::option::*; #[test] fn test_get_ptr() { @@ -28,15 +28,15 @@ fn test_get_str() { #[test] fn test_get_resource() { - use std::rc::Rc; use core::cell::RefCell; + use std::rc::Rc; struct R { - i: Rc>, + i: Rc>, } - impl Drop for R { - fn drop(&mut self) { + impl Drop for R { + fn drop(&mut self) { let ii = &*self.i; let i = *ii.borrow(); *ii.borrow_mut() = i + 1; @@ -44,9 +44,7 @@ fn test_get_resource() { } fn r(i: Rc>) -> R { - R { - i, - } + R { i } } let i = Rc::new(RefCell::new(0)); @@ -70,7 +68,8 @@ fn test_option_dance() { assert!(y.is_none()); } -#[test] #[should_panic] +#[test] +#[should_panic] fn test_option_too_much_dance() { struct A; let mut y = Some(A); @@ -210,7 +209,7 @@ fn test_mut_iter() { fn test_ord() { let small = Some(1.0f64); let big = Some(5.0f64); - let nan = Some(0.0f64/0.0); + let nan = Some(0.0f64 / 0.0); assert!(!(nan < big)); assert!(!(nan > big)); assert!(small < big); @@ -226,9 +225,7 @@ fn test_collect() { let v: Option> = (0..3).map(|x| Some(x)).collect(); assert!(v == Some(vec![0, 1, 2])); - let v: Option> = (0..3).map(|x| { - if x > 1 { None } else { Some(x) } - }).collect(); + let v: Option> = (0..3).map(|x| if x > 1 { None } else { Some(x) }).collect(); assert!(v == None); // test that it does not take more elements than it needs diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index 1a6be3a9bb..eea736bc88 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -1,14 +1,14 @@ -use core::ptr::*; use core::cell::RefCell; +use core::ptr::*; #[test] fn test() { unsafe { struct Pair { fst: isize, - snd: isize + snd: isize, }; - let mut p = Pair {fst: 10, snd: 20}; + let mut p = Pair { fst: 10, snd: 20 }; let pptr: *mut Pair = &mut p; let iptr: *mut isize = pptr as *mut isize; assert_eq!(*iptr, 10); @@ -16,7 +16,7 @@ fn test() { assert_eq!(*iptr, 30); assert_eq!(p.fst, 30); - *pptr = Pair {fst: 50, snd: 60}; + *pptr = Pair { fst: 50, snd: 60 }; assert_eq!(*iptr, 50); assert_eq!(p.fst, 50); assert_eq!(p.snd, 60); @@ -25,17 +25,11 @@ fn test() { let mut v1 = vec![0u16, 0u16, 0u16]; copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1); - assert!((v1[0] == 0u16 && - v1[1] == 32001u16 && - v1[2] == 0u16)); + assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1); - assert!((v1[0] == 32002u16 && - v1[1] == 32001u16 && - v1[2] == 0u16)); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16)); copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1); - assert!((v1[0] == 32002u16 && - v1[1] == 32001u16 && - v1[2] == 32000u16)); + assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16)); } } @@ -208,7 +202,7 @@ fn test_ptr_addition() { #[test] fn test_ptr_subtraction() { unsafe { - let xs = vec![0,1,2,3,4,5,6,7,8,9]; + let xs = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let mut idx = 9; let ptr = xs.as_ptr(); @@ -229,7 +223,7 @@ fn test_ptr_subtraction() { m_ptr = m_ptr.offset(-1); } - assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]); + assert_eq!(xs_mut, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]); } } @@ -237,7 +231,9 @@ fn test_ptr_subtraction() { fn test_set_memory() { let mut xs = [0u8; 20]; let ptr = xs.as_mut_ptr(); - unsafe { write_bytes(ptr, 5u8, xs.len()); } + unsafe { + write_bytes(ptr, 5u8, xs.len()); + } assert!(xs == [5u8; 20]); } @@ -257,10 +253,10 @@ fn test_unsized_nonnull() { #[no_mangle] pub fn test_variadic_fnptr() { use core::hash::{Hash, SipHasher}; - extern { + extern "C" { fn test_variadic_fnptr(_: u64, ...) -> f64; } - let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr; + let p: unsafe extern "C" fn(u64, ...) -> f64 = test_variadic_fnptr; let q = p.clone(); assert_eq!(p, q); assert!(!(p < q)); @@ -285,13 +281,15 @@ fn write_unaligned_drop() { { let c = Dropper(0); let mut t = Dropper(1); - unsafe { write_unaligned(&mut t, c); } + unsafe { + write_unaligned(&mut t, c); + } } DROPS.with(|d| assert_eq!(*d.borrow(), [0])); } #[test] -#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset` +#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset` fn align_offset_zst() { // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at // all, because no amount of elements will align the pointer. @@ -306,24 +304,29 @@ fn align_offset_zst() { } #[test] -#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset` +#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset` fn align_offset_stride1() { // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to // number of bytes. let mut align = 1; while align < 1024 { - for ptr in 1..2*align { + for ptr in 1..2 * align { let expected = ptr % align; let offset = if expected == 0 { 0 } else { align - expected }; - assert_eq!((ptr as *const u8).align_offset(align), offset, - "ptr = {}, align = {}, size = 1", ptr, align); + assert_eq!( + (ptr as *const u8).align_offset(align), + offset, + "ptr = {}, align = {}, size = 1", + ptr, + align + ); } align = (align + 1).next_power_of_two(); } } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn align_offset_weird_strides() { #[repr(packed)] struct A3(u16, u8); @@ -353,8 +356,14 @@ fn align_offset_weird_strides() { } let got = ptr.align_offset(align); if got != expected { - eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr, - ::std::mem::size_of::(), align, expected, got); + eprintln!( + "aligning {:p} (with stride of {}) to {}, expected {}, got {}", + ptr, + ::std::mem::size_of::(), + align, + expected, + got + ); return true; } return false; @@ -365,7 +374,7 @@ fn align_offset_weird_strides() { let mut align = 1; let mut x = false; while align < 1024 { - for ptr in 1usize..4*align { + for ptr in 1usize..4 * align { unsafe { x |= test_weird_stride::(ptr as *const A3, align); x |= test_weird_stride::(ptr as *const A4, align); diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 6609bc3135..cc274b4aec 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -1,4 +1,4 @@ -use core::result::Result::{Ok, Err}; +use core::result::Result::{Err, Ok}; #[test] fn test_position() { @@ -50,8 +50,14 @@ fn test_binary_search() { assert_eq!(b.binary_search(&0), Err(0)); assert_eq!(b.binary_search(&1), Ok(0)); assert_eq!(b.binary_search(&2), Err(1)); - assert!(match b.binary_search(&3) { Ok(1..=3) => true, _ => false }); - assert!(match b.binary_search(&3) { Ok(1..=3) => true, _ => false }); + assert!(match b.binary_search(&3) { + Ok(1..=3) => true, + _ => false, + }); + assert!(match b.binary_search(&3) { + Ok(1..=3) => true, + _ => false, + }); assert_eq!(b.binary_search(&4), Err(4)); assert_eq!(b.binary_search(&5), Err(4)); assert_eq!(b.binary_search(&6), Err(4)); @@ -187,7 +193,8 @@ fn test_chunks_zip() { let v1: &[i32] = &[0, 1, 2, 3, 4]; let v2: &[i32] = &[6, 7, 8, 9, 10]; - let res = v1.chunks(2) + let res = v1 + .chunks(2) .zip(v2.chunks(2)) .map(|(a, b)| a.iter().sum::() + b.iter().sum::()) .collect::>(); @@ -339,7 +346,8 @@ fn test_chunks_exact_zip() { let v1: &[i32] = &[0, 1, 2, 3, 4]; let v2: &[i32] = &[6, 7, 8, 9, 10]; - let res = v1.chunks_exact(2) + let res = v1 + .chunks_exact(2) .zip(v2.chunks_exact(2)) .map(|(a, b)| a.iter().sum::() + b.iter().sum::()) .collect::>(); @@ -482,7 +490,8 @@ fn test_rchunks_zip() { let v1: &[i32] = &[0, 1, 2, 3, 4]; let v2: &[i32] = &[6, 7, 8, 9, 10]; - let res = v1.rchunks(2) + let res = v1 + .rchunks(2) .zip(v2.rchunks(2)) .map(|(a, b)| a.iter().sum::() + b.iter().sum::()) .collect::>(); @@ -619,7 +628,8 @@ fn test_rchunks_exact_zip() { let v1: &[i32] = &[0, 1, 2, 3, 4]; let v2: &[i32] = &[6, 7, 8, 9, 10]; - let res = v1.rchunks_exact(2) + let res = v1 + .rchunks_exact(2) .zip(v2.rchunks_exact(2)) .map(|(a, b)| a.iter().sum::() + b.iter().sum::()) .collect::>(); @@ -756,7 +766,8 @@ fn test_windows_zip() { let v1: &[i32] = &[0, 1, 2, 3, 4]; let v2: &[i32] = &[6, 7, 8, 9, 10]; - let res = v1.windows(2) + let res = v1 + .windows(2) .zip(v2.windows(2)) .map(|(a, b)| a.iter().sum::() + b.iter().sum::()) .collect::>(); @@ -769,11 +780,11 @@ fn test_windows_zip() { fn test_iter_ref_consistency() { use std::fmt::Debug; - fn test(x : T) { - let v : &[T] = &[x, x, x]; - let v_ptrs : [*const T; 3] = match v { + fn test(x: T) { + let v: &[T] = &[x, x, x]; + let v_ptrs: [*const T; 3] = match v { [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _], - _ => unreachable!() + _ => unreachable!(), }; let len = v.len(); @@ -817,19 +828,20 @@ fn test_iter_ref_consistency() { assert_eq!(it.size_hint(), (remaining, Some(remaining))); let prev = it.next_back().unwrap(); - assert_eq!(prev as *const _, v_ptrs[remaining-1]); + assert_eq!(prev as *const _, v_ptrs[remaining - 1]); } assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next_back(), None, "The final call to next_back() should return None"); } } - fn test_mut(x : T) { - let v : &mut [T] = &mut [x, x, x]; - let v_ptrs : [*mut T; 3] = match v { - [ref v1, ref v2, ref v3] => - [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _], - _ => unreachable!() + fn test_mut(x: T) { + let v: &mut [T] = &mut [x, x, x]; + let v_ptrs: [*mut T; 3] = match v { + [ref v1, ref v2, ref v3] => { + [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _] + } + _ => unreachable!(), }; let len = v.len(); @@ -873,7 +885,7 @@ fn test_iter_ref_consistency() { assert_eq!(it.size_hint(), (remaining, Some(remaining))); let prev = it.next_back().unwrap(); - assert_eq!(prev as *mut _, v_ptrs[remaining-1]); + assert_eq!(prev as *mut _, v_ptrs[remaining - 1]); } assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next_back(), None, "The final call to next_back() should return None"); @@ -897,8 +909,7 @@ mod slice_index { // This checks all six indexing methods, given an input range that // should succeed. (it is NOT suitable for testing invalid inputs) macro_rules! assert_range_eq { - ($arr:expr, $range:expr, $expected:expr) - => { + ($arr:expr, $range:expr, $expected:expr) => { let mut arr = $arr; let mut expected = $expected; { @@ -909,7 +920,8 @@ mod slice_index { assert_eq!(s.get($range), Some(expected), "(in assertion for: get)"); unsafe { assert_eq!( - s.get_unchecked($range), expected, + s.get_unchecked($range), + expected, "(in assertion for: get_unchecked)", ); } @@ -918,22 +930,21 @@ mod slice_index { let s: &mut [_] = &mut arr; let expected: &mut [_] = &mut expected; + assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",); assert_eq!( - &mut s[$range], expected, - "(in assertion for: index_mut)", - ); - assert_eq!( - s.get_mut($range), Some(&mut expected[..]), + s.get_mut($range), + Some(&mut expected[..]), "(in assertion for: get_mut)", ); unsafe { assert_eq!( - s.get_unchecked_mut($range), expected, + s.get_unchecked_mut($range), + expected, "(in assertion for: get_unchecked_mut)", ); } } - } + }; } // Make sure the macro can actually detect bugs, @@ -1126,8 +1137,8 @@ fn test_find_rfind() { #[test] fn test_iter_folds() { let a = [1, 2, 3, 4, 5]; // len>4 so the unroll is used - assert_eq!(a.iter().fold(0, |acc, &x| 2*acc + x), 57); - assert_eq!(a.iter().rfold(0, |acc, &x| 2*acc + x), 129); + assert_eq!(a.iter().fold(0, |acc, &x| 2 * acc + x), 57); + assert_eq!(a.iter().rfold(0, |acc, &x| 2 * acc + x), 129); let fold = |acc: i32, &x| acc.checked_mul(2)?.checked_add(x); assert_eq!(a.iter().try_fold(0, &fold), Some(57)); assert_eq!(a.iter().try_rfold(0, &fold), Some(129)); @@ -1172,7 +1183,7 @@ fn test_rotate_right() { } #[test] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn brute_force_rotate_test_0() { // In case of edge cases involving multiple algorithms let n = 300; @@ -1214,7 +1225,7 @@ fn brute_force_rotate_test_1() { fn sort_unstable() { use core::cmp::Ordering::{Equal, Greater, Less}; use core::slice::heapsort; - use rand::{SeedableRng, Rng, rngs::StdRng, seq::SliceRandom}; + use rand::{rngs::StdRng, seq::SliceRandom, Rng, SeedableRng}; #[cfg(not(miri))] // Miri is too slow let large_range = 500..510; @@ -1291,12 +1302,12 @@ fn sort_unstable() { #[test] #[cfg(not(target_arch = "wasm32"))] -#[cfg(not(miri))] // Miri is too slow +#[cfg_attr(miri, ignore)] // Miri is too slow fn partition_at_index() { use core::cmp::Ordering::{Equal, Greater, Less}; use rand::rngs::StdRng; use rand::seq::SliceRandom; - use rand::{SeedableRng, Rng}; + use rand::{Rng, SeedableRng}; let mut rng = StdRng::from_entropy(); @@ -1494,7 +1505,7 @@ pub mod memchr { } #[test] -#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset` +#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset` fn test_align_to_simple() { let bytes = [1u8, 2, 3, 4, 5, 6, 7]; let (prefix, aligned, suffix) = unsafe { bytes.align_to::() }; @@ -1504,9 +1515,15 @@ fn test_align_to_simple() { let expect2 = [1 | 2 << 8, 3 | 4 << 8, 5 | 6 << 8]; let expect3 = [2 << 8 | 3, 4 << 8 | 5, 6 << 8 | 7]; let expect4 = [2 | 3 << 8, 4 | 5 << 8, 6 | 7 << 8]; - assert!(aligned == expect1 || aligned == expect2 || aligned == expect3 || aligned == expect4, - "aligned={:?} expected={:?} || {:?} || {:?} || {:?}", - aligned, expect1, expect2, expect3, expect4); + assert!( + aligned == expect1 || aligned == expect2 || aligned == expect3 || aligned == expect4, + "aligned={:?} expected={:?} || {:?} || {:?} || {:?}", + aligned, + expect1, + expect2, + expect3, + expect4 + ); } #[test] @@ -1518,12 +1535,22 @@ fn test_align_to_zst() { } #[test] -#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset` +#[cfg_attr(miri, ignore)] // Miri does not compute a maximal `mid` for `align_offset` fn test_align_to_non_trivial() { - #[repr(align(8))] struct U64(u64, u64); - #[repr(align(8))] struct U64U64U32(u64, u64, u32); - let data = [U64(1, 2), U64(3, 4), U64(5, 6), U64(7, 8), U64(9, 10), U64(11, 12), U64(13, 14), - U64(15, 16)]; + #[repr(align(8))] + struct U64(u64, u64); + #[repr(align(8))] + struct U64U64U32(u64, u64, u32); + let data = [ + U64(1, 2), + U64(3, 4), + U64(5, 6), + U64(7, 8), + U64(9, 10), + U64(11, 12), + U64(13, 14), + U64(15, 16), + ]; let (prefix, aligned, suffix) = unsafe { data.align_to::() }; assert_eq!(aligned.len(), 4); assert_eq!(prefix.len() + suffix.len(), 2); @@ -1538,7 +1565,7 @@ fn test_align_to_empty_mid() { let bytes = [1, 2, 3, 4, 5, 6, 7]; type Chunk = u32; for offset in 0..4 { - let (_, mid, _) = unsafe { bytes[offset..offset+1].align_to::() }; + let (_, mid, _) = unsafe { bytes[offset..offset + 1].align_to::() }; assert_eq!(mid.as_ptr() as usize % mem::align_of::(), 0); } } diff --git a/src/libcore/tests/str_lossy.rs b/src/libcore/tests/str_lossy.rs index f9fd333cca..d4b47a4708 100644 --- a/src/libcore/tests/str_lossy.rs +++ b/src/libcore/tests/str_lossy.rs @@ -3,65 +3,65 @@ use core::str::lossy::*; #[test] fn chunks() { let mut iter = Utf8Lossy::from_bytes(b"hello").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); let mut iter = Utf8Lossy::from_bytes("ศไทย中华Việt Nam".as_bytes()).chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); let mut iter = Utf8Lossy::from_bytes(b"Hello\xC2 There\xFF Goodbye").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); let mut iter = Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); let mut iter = Utf8Lossy::from_bytes(b"\xF5foo\xF5\x80bar").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); let mut iter = Utf8Lossy::from_bytes(b"\xF1foo\xF1\x80bar\xF1\x80\x80baz").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); let mut iter = Utf8Lossy::from_bytes(b"\xF4foo\xF4\x80bar\xF4\xBFbaz").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); let mut iter = Utf8Lossy::from_bytes(b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); // surrogates let mut iter = Utf8Lossy::from_bytes(b"\xED\xA0\x80foo\xED\xBF\xBFbar").chunks(); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF", }), iter.next()); - assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"", }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next()); + assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"" }), iter.next()); assert_eq!(None, iter.next()); } @@ -69,13 +69,17 @@ fn chunks() { fn display() { assert_eq!( "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", - &Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string()); + &Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string() + ); } #[test] fn debug() { assert_eq!( "\"Hello\\xc0\\x80 There\\xe6\\x83 Goodbye\\u{10d4ea}\"", - &format!("{:?}", Utf8Lossy::from_bytes( - b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa"))); + &format!( + "{:?}", + Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa") + ) + ); } diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs index fac70c468c..273f1258bb 100644 --- a/src/libcore/tests/time.rs +++ b/src/libcore/tests/time.rs @@ -3,10 +3,11 @@ use core::time::Duration; #[test] fn creation() { assert_ne!(Duration::from_secs(1), Duration::from_secs(0)); - assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), - Duration::from_secs(3)); - assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), - Duration::new(4, 10 * 1_000_000)); + assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), Duration::from_secs(3)); + assert_eq!( + Duration::from_millis(10) + Duration::from_secs(4), + Duration::new(4, 10 * 1_000_000) + ); assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); } @@ -68,29 +69,25 @@ fn nanos() { #[test] fn add() { - assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), - Duration::new(1, 1)); + assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), Duration::new(1, 1)); } #[test] fn checked_add() { - assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), - Some(Duration::new(0, 1))); - assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), - Some(Duration::new(1, 1))); + assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1))); + assert_eq!( + Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), + Some(Duration::new(1, 1)) + ); assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None); } #[test] fn sub() { - assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), - Duration::new(0, 1)); - assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), - Duration::new(0, 999_999_999)); + assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), Duration::new(0, 1)); + assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), Duration::new(0, 999_999_999)); } #[test] @@ -99,8 +96,7 @@ fn checked_sub() { let one_nano = Duration::new(0, 1); let one_sec = Duration::new(1, 0); assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); - assert_eq!(one_sec.checked_sub(one_nano), - Some(Duration::new(0, 999_999_999))); + assert_eq!(one_sec.checked_sub(one_nano), Some(Duration::new(0, 999_999_999))); assert_eq!(zero.checked_sub(one_nano), None); assert_eq!(zero.checked_sub(one_sec), None); } @@ -122,8 +118,7 @@ fn mul() { assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); - assert_eq!(Duration::new(0, 500_000_001) * 4000, - Duration::new(2000, 4000)); + assert_eq!(Duration::new(0, 500_000_001) * 4000, Duration::new(2000, 4000)); } #[test] @@ -131,8 +126,7 @@ fn checked_mul() { assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), - Some(Duration::new(2000, 4000))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), Some(Duration::new(2000, 4000))); assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None); } @@ -140,8 +134,7 @@ fn checked_mul() { fn div() { assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); - assert_eq!(Duration::new(99, 999_999_000) / 100, - Duration::new(0, 999_999_990)); + assert_eq!(Duration::new(99, 999_999_000) / 100, Duration::new(0, 999_999_990)); } #[test] @@ -162,7 +155,7 @@ fn correct_sum() { Duration::new(5, 0), ]; let sum = durations.iter().sum::(); - assert_eq!(sum, Duration::new(1+2+5+4, 1_000_000_000 - 5)); + assert_eq!(sum, Duration::new(1 + 2 + 5 + 4, 1_000_000_000 - 5)); } #[test] @@ -286,9 +279,9 @@ fn debug_formatting_precision_two() { #[test] fn debug_formatting_precision_high() { - assert_eq!(format!("{:.5?}", Duration::new(0, 23_678)), "23.67800µs"); + assert_eq!(format!("{:.5?}", Duration::new(0, 23_678)), "23.67800µs"); - assert_eq!(format!("{:.9?}", Duration::new(1, 000_000_000)), "1.000000000s"); + assert_eq!(format!("{:.9?}", Duration::new(1, 000_000_000)), "1.000000000s"); assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s"); assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s"); } diff --git a/src/libcore/tests/tuple.rs b/src/libcore/tests/tuple.rs index c7ed1612dd..3a2914698c 100644 --- a/src/libcore/tests/tuple.rs +++ b/src/libcore/tests/tuple.rs @@ -1,4 +1,4 @@ -use std::cmp::Ordering::{Equal, Less, Greater}; +use std::cmp::Ordering::{Equal, Greater, Less}; use std::f64::NAN; #[test] diff --git a/src/libcore/time.rs b/src/libcore/time.rs index 5a0e4388e0..7d04cfb5da 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -12,9 +12,9 @@ //! assert_eq!(Duration::new(5, 0), Duration::from_secs(5)); //! ``` -use crate::{fmt, u64}; use crate::iter::Sum; -use crate::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; +use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; +use crate::{fmt, u64}; const NANOS_PER_SEC: u32 = 1_000_000_000; const NANOS_PER_MILLI: u32 = 1_000_000; @@ -130,9 +130,10 @@ impl Duration { /// ``` #[stable(feature = "duration", since = "1.3.0")] #[inline] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_consts", since = "1.32.0"))] pub fn new(secs: u64, nanos: u32) -> Duration { - let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64) - .expect("overflow in Duration::new"); + let secs = + secs.checked_add((nanos / NANOS_PER_SEC) as u64).expect("overflow in Duration::new"); let nanos = nanos % NANOS_PER_SEC; Duration { secs, nanos } } @@ -152,6 +153,7 @@ impl Duration { #[stable(feature = "duration", since = "1.3.0")] #[inline] #[rustc_promotable] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_consts", since = "1.32.0"))] pub const fn from_secs(secs: u64) -> Duration { Duration { secs, nanos: 0 } } @@ -171,6 +173,7 @@ impl Duration { #[stable(feature = "duration", since = "1.3.0")] #[inline] #[rustc_promotable] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_consts", since = "1.32.0"))] pub const fn from_millis(millis: u64) -> Duration { Duration { secs: millis / MILLIS_PER_SEC, @@ -193,6 +196,7 @@ impl Duration { #[stable(feature = "duration_from_micros", since = "1.27.0")] #[inline] #[rustc_promotable] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_consts", since = "1.32.0"))] pub const fn from_micros(micros: u64) -> Duration { Duration { secs: micros / MICROS_PER_SEC, @@ -215,6 +219,7 @@ impl Duration { #[stable(feature = "duration_extras", since = "1.27.0")] #[inline] #[rustc_promotable] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_consts", since = "1.32.0"))] pub const fn from_nanos(nanos: u64) -> Duration { Duration { secs: nanos / (NANOS_PER_SEC as u64), @@ -251,8 +256,11 @@ impl Duration { /// /// [`subsec_nanos`]: #method.subsec_nanos #[stable(feature = "duration", since = "1.3.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration", since = "1.32.0"))] #[inline] - pub const fn as_secs(&self) -> u64 { self.secs } + pub const fn as_secs(&self) -> u64 { + self.secs + } /// Returns the fractional part of this `Duration`, in whole milliseconds. /// @@ -270,8 +278,11 @@ impl Duration { /// assert_eq!(duration.subsec_millis(), 432); /// ``` #[stable(feature = "duration_extras", since = "1.27.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_extras", since = "1.32.0"))] #[inline] - pub const fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI } + pub const fn subsec_millis(&self) -> u32 { + self.nanos / NANOS_PER_MILLI + } /// Returns the fractional part of this `Duration`, in whole microseconds. /// @@ -289,8 +300,11 @@ impl Duration { /// assert_eq!(duration.subsec_micros(), 234_567); /// ``` #[stable(feature = "duration_extras", since = "1.27.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_extras", since = "1.32.0"))] #[inline] - pub const fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO } + pub const fn subsec_micros(&self) -> u32 { + self.nanos / NANOS_PER_MICRO + } /// Returns the fractional part of this `Duration`, in nanoseconds. /// @@ -308,8 +322,11 @@ impl Duration { /// assert_eq!(duration.subsec_nanos(), 10_000_000); /// ``` #[stable(feature = "duration", since = "1.3.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration", since = "1.32.0"))] #[inline] - pub const fn subsec_nanos(&self) -> u32 { self.nanos } + pub const fn subsec_nanos(&self) -> u32 { + self.nanos + } /// Returns the total number of whole milliseconds contained by this `Duration`. /// @@ -322,6 +339,7 @@ impl Duration { /// assert_eq!(duration.as_millis(), 5730); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_as_u128", since = "1.33.0"))] #[inline] pub const fn as_millis(&self) -> u128 { self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128 @@ -338,6 +356,7 @@ impl Duration { /// assert_eq!(duration.as_micros(), 5730023); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_as_u128", since = "1.33.0"))] #[inline] pub const fn as_micros(&self) -> u128 { self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128 @@ -354,6 +373,7 @@ impl Duration { /// assert_eq!(duration.as_nanos(), 5730023852); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] + #[cfg_attr(not(bootstrap), rustc_const_stable(feature = "duration_as_u128", since = "1.33.0"))] #[inline] pub const fn as_nanos(&self) -> u128 { self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128 @@ -388,10 +408,7 @@ impl Duration { } } debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { - secs, - nanos, - }) + Some(Duration { secs, nanos }) } else { None } @@ -455,14 +472,11 @@ impl Duration { let total_nanos = self.nanos as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; - if let Some(secs) = self.secs - .checked_mul(rhs as u64) - .and_then(|s| s.checked_add(extra_secs)) { + if let Some(secs) = + self.secs.checked_mul(rhs as u64).and_then(|s| s.checked_add(extra_secs)) + { debug_assert!(nanos < NANOS_PER_SEC); - Some(Duration { - secs, - nanos, - }) + Some(Duration { secs, nanos }) } else { None } @@ -549,9 +563,8 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn from_secs_f64(secs: f64) -> Duration { - const MAX_NANOS_F64: f64 = - ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64; - let nanos = secs * (NANOS_PER_SEC as f64); + const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64; + let nanos = secs * (NANOS_PER_SEC as f64); if !nanos.is_finite() { panic!("got non-finite value when converting float to duration"); } @@ -561,7 +574,7 @@ impl Duration { if nanos < 0.0 { panic!("underflow when converting float to duration"); } - let nanos = nanos as u128; + let nanos = nanos as u128; Duration { secs: (nanos / (NANOS_PER_SEC as u128)) as u64, nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, @@ -584,9 +597,8 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn from_secs_f32(secs: f32) -> Duration { - const MAX_NANOS_F32: f32 = - ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f32; - let nanos = secs * (NANOS_PER_SEC as f32); + const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32; + let nanos = secs * (NANOS_PER_SEC as f32); if !nanos.is_finite() { panic!("got non-finite value when converting float to duration"); } @@ -596,7 +608,7 @@ impl Duration { if nanos < 0.0 { panic!("underflow when converting float to duration"); } - let nanos = nanos as u128; + let nanos = nanos as u128; Duration { secs: (nanos / (NANOS_PER_SEC as u128)) as u64, nanos: (nanos % (NANOS_PER_SEC as u128)) as u32, @@ -799,9 +811,8 @@ macro_rules! sum_durations { let mut total_nanos: u64 = 0; for entry in $iter { - total_secs = total_secs - .checked_add(entry.secs) - .expect("overflow in iter::sum over durations"); + total_secs = + total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations"); total_nanos = match total_nanos.checked_add(entry.nanos as u64) { Some(n) => n, None => { @@ -816,23 +827,20 @@ macro_rules! sum_durations { .checked_add(total_nanos / NANOS_PER_SEC as u64) .expect("overflow in iter::sum over durations"); total_nanos = total_nanos % NANOS_PER_SEC as u64; - Duration { - secs: total_secs, - nanos: total_nanos as u32, - } + Duration { secs: total_secs, nanos: total_nanos as u32 } }}; } #[stable(feature = "duration_sum", since = "1.16.0")] impl Sum for Duration { - fn sum>(iter: I) -> Duration { + fn sum>(iter: I) -> Duration { sum_durations!(iter) } } #[stable(feature = "duration_sum", since = "1.16.0")] impl<'a> Sum<&'a Duration> for Duration { - fn sum>(iter: I) -> Duration { + fn sum>(iter: I) -> Duration { sum_durations!(iter) } } @@ -920,11 +928,9 @@ impl fmt::Debug for Duration { if end == 0 { write!(f, "{}", integer_part) } else { - // We are only writing ASCII digits into the buffer and it was + // SAFETY: We are only writing ASCII digits into the buffer and it was // initialized with '0's, so it contains valid UTF8. - let s = unsafe { - crate::str::from_utf8_unchecked(&buf[..end]) - }; + let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) }; // If the user request a precision > 9, we pad '0's at the end. let w = f.precision().unwrap_or(pos); diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index f05780f4a6..9f8a3a1de4 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -1,7 +1,7 @@ // See src/libstd/primitive_docs.rs for documentation. -use crate::cmp::*; use crate::cmp::Ordering::*; +use crate::cmp::*; // macro for implementing n-ary tuple functions and operations macro_rules! tuple_impls { diff --git a/src/libcore/unicode/bool_trie.rs b/src/libcore/unicode/bool_trie.rs index 39584d346e..b7fba88a54 100644 --- a/src/libcore/unicode/bool_trie.rs +++ b/src/libcore/unicode/bool_trie.rs @@ -19,16 +19,16 @@ /// non-BMP range of most Unicode sets. pub struct BoolTrie { // 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences) - pub r1: [u64; 32], // leaves + pub r1: [u64; 32], // leaves // 0x800..0x10000 (corresponding to 3 byte utf-8 sequences) pub r2: [u8; 992], // first level - pub r3: &'static [u64], // leaves + pub r3: &'static [u64], // leaves // 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences) - pub r4: [u8; 256], // first level - pub r5: &'static [u8], // second level - pub r6: &'static [u64], // leaves + pub r4: [u8; 256], // first level + pub r5: &'static [u8], // second level + pub r6: &'static [u64], // leaves } impl BoolTrie { pub fn lookup(&self, c: char) -> bool { @@ -48,7 +48,7 @@ impl BoolTrie { pub struct SmallBoolTrie { pub(crate) r1: &'static [u8], // first level - pub(crate) r2: &'static [u64], // leaves + pub(crate) r2: &'static [u64], // leaves } impl SmallBoolTrie { diff --git a/src/libcore/unicode/printable.py b/src/libcore/unicode/printable.py old mode 100644 new mode 100755 index 4e8b4ecad0..91db6381c9 --- a/src/libcore/unicode/printable.py +++ b/src/libcore/unicode/printable.py @@ -111,16 +111,19 @@ def compress_normal(normal): return compressed def print_singletons(uppers, lowers, uppersname, lowersname): + print("#[rustfmt::skip]") print("const {}: &[(u8, u8)] = &[".format(uppersname)) for u, c in uppers: print(" ({:#04x}, {}),".format(u, c)) print("];") + print("#[rustfmt::skip]") print("const {}: &[u8] = &[".format(lowersname)) for i in range(0, len(lowers), 8): print(" {}".format(" ".join("{:#04x},".format(l) for l in lowers[i:i+8]))) print("];") def print_normal(normal, normalname): + print("#[rustfmt::skip]") print("const {}: &[u8] = &[".format(normalname)) for v in normal: print(" {}".format(" ".join("{:#04x},".format(i) for i in v))) @@ -170,8 +173,7 @@ def main(): // NOTE: The following code was generated by "src/libcore/unicode/printable.py", // do not edit directly! -fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], - normal: &[u8]) -> bool { +fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool { let xupper = (x >> 8) as u8; let mut lowerstart = 0; for &(upper, lowercount) in singletonuppers { diff --git a/src/libcore/unicode/printable.rs b/src/libcore/unicode/printable.rs index d411dda7dc..eee9ea52ef 100644 --- a/src/libcore/unicode/printable.rs +++ b/src/libcore/unicode/printable.rs @@ -1,8 +1,7 @@ // NOTE: The following code was generated by "src/libcore/unicode/printable.py", // do not edit directly! -fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], - normal: &[u8]) -> bool { +fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool { let xupper = (x >> 8) as u8; let mut lowerstart = 0; for &(upper, lowercount) in singletonuppers { @@ -70,6 +69,7 @@ pub(crate) fn is_printable(x: char) -> bool { } } +#[rustfmt::skip] const SINGLETONS0U: &[(u8, u8)] = &[ (0x00, 1), (0x03, 5), @@ -113,6 +113,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0xfe, 3), (0xff, 9), ]; +#[rustfmt::skip] const SINGLETONS0L: &[u8] = &[ 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90, 0x1c, 0x1d, 0xdd, 0x0e, @@ -152,6 +153,7 @@ const SINGLETONS0L: &[u8] = &[ 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, ]; +#[rustfmt::skip] const SINGLETONS1U: &[(u8, u8)] = &[ (0x00, 6), (0x01, 1), @@ -189,6 +191,7 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0xf9, 6), (0xfa, 2), ]; +#[rustfmt::skip] const SINGLETONS1L: &[u8] = &[ 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e, @@ -212,6 +215,7 @@ const SINGLETONS1L: &[u8] = &[ 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x0c, 0x72, 0xa3, 0xa4, 0xcb, 0xcc, 0x6e, 0x6f, ]; +#[rustfmt::skip] const NORMAL0: &[u8] = &[ 0x00, 0x20, 0x5f, 0x22, @@ -355,6 +359,7 @@ const NORMAL0: &[u8] = &[ 0x1b, 0x03, 0x0f, 0x0d, ]; +#[rustfmt::skip] const NORMAL1: &[u8] = &[ 0x5e, 0x22, 0x7b, 0x05, diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs index 5b5be48543..3fa125e8fe 100644 --- a/src/libcore/unicode/tables.rs +++ b/src/libcore/unicode/tables.rs @@ -2,19 +2,16 @@ #![allow(missing_docs, non_upper_case_globals, non_snake_case, clippy::unreadable_literal)] -use crate::unicode::version::UnicodeVersion; use crate::unicode::bool_trie::{BoolTrie, SmallBoolTrie}; +use crate::unicode::version::UnicodeVersion; /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of /// `char` and `str` methods are based on. #[unstable(feature = "unicode_version", issue = "49726")] -pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion { - major: 12, - minor: 1, - micro: 0, - _priv: (), -}; +pub const UNICODE_VERSION: UnicodeVersion = + UnicodeVersion { major: 12, minor: 1, micro: 0, _priv: () }; pub(crate) mod general_category { + #[rustfmt::skip] const Cc_table: &super::SmallBoolTrie = &super::SmallBoolTrie { r1: &[ 0, 1, 0 @@ -28,6 +25,7 @@ pub(crate) mod general_category { Cc_table.lookup(c) } + #[rustfmt::skip] const N_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x03ff000000000000, 0x0000000000000000, 0x720c000000000000, 0x0000000000000000, @@ -138,10 +136,10 @@ pub(crate) mod general_category { pub fn N(c: char) -> bool { N_table.lookup(c) } - } pub(crate) mod derived_property { + #[rustfmt::skip] const Alphabetic_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, @@ -327,6 +325,7 @@ pub(crate) mod derived_property { Alphabetic_table.lookup(c) } + #[rustfmt::skip] const Case_Ignorable_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0400408000000000, 0x0000000140000000, 0x0190a10000000000, 0x0000000000000000, @@ -464,6 +463,7 @@ pub(crate) mod derived_property { Case_Ignorable_table.lookup(c) } + #[rustfmt::skip] const Cased_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, @@ -565,6 +565,7 @@ pub(crate) mod derived_property { Cased_table.lookup(c) } + #[rustfmt::skip] const Grapheme_Extend_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, @@ -689,6 +690,7 @@ pub(crate) mod derived_property { Grapheme_Extend_table.lookup(c) } + #[rustfmt::skip] const Lowercase_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x07fffffe00000000, 0x0420040000000000, 0xff7fffff80000000, @@ -789,6 +791,7 @@ pub(crate) mod derived_property { Lowercase_table.lookup(c) } + #[rustfmt::skip] const Uppercase_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x0000000007fffffe, 0x0000000000000000, 0x000000007f7fffff, @@ -889,10 +892,10 @@ pub(crate) mod derived_property { pub fn Uppercase(c: char) -> bool { Uppercase_table.lookup(c) } - } pub(crate) mod property { + #[rustfmt::skip] const White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { r1: &[ 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -912,20 +915,19 @@ pub(crate) mod property { pub fn White_Space(c: char) -> bool { White_Space_table.lookup(c) } - } pub(crate) mod conversions { pub fn to_lower(c: char) -> [char; 3] { match bsearch_case_table(c, to_lowercase_table) { - None => [c, '\0', '\0'], + None => [c, '\0', '\0'], Some(index) => to_lowercase_table[index].1, } } pub fn to_upper(c: char) -> [char; 3] { match bsearch_case_table(c, to_uppercase_table) { - None => [c, '\0', '\0'], + None => [c, '\0', '\0'], Some(index) => to_uppercase_table[index].1, } } @@ -934,6 +936,7 @@ pub(crate) mod conversions { table.binary_search_by(|&(key, _)| key.cmp(&c)).ok() } + #[rustfmt::skip] const to_lowercase_table: &[(char, [char; 3])] = &[ ('\u{41}', ['\u{61}', '\0', '\0']), ('\u{42}', ['\u{62}', '\0', '\0']), ('\u{43}', ['\u{63}', '\0', '\0']), ('\u{44}', ['\u{64}', '\0', '\0']), ('\u{45}', ['\u{65}', '\0', @@ -1558,6 +1561,7 @@ pub(crate) mod conversions { ('\u{1e920}', ['\u{1e942}', '\0', '\0']), ('\u{1e921}', ['\u{1e943}', '\0', '\0']) ]; + #[rustfmt::skip] const to_uppercase_table: &[(char, [char; 3])] = &[ ('\u{61}', ['\u{41}', '\0', '\0']), ('\u{62}', ['\u{42}', '\0', '\0']), ('\u{63}', ['\u{43}', '\0', '\0']), ('\u{64}', ['\u{44}', '\0', '\0']), ('\u{65}', ['\u{45}', '\0', @@ -2228,5 +2232,4 @@ pub(crate) mod conversions { ('\u{1e940}', ['\u{1e91e}', '\0', '\0']), ('\u{1e941}', ['\u{1e91f}', '\0', '\0']), ('\u{1e942}', ['\u{1e920}', '\0', '\0']), ('\u{1e943}', ['\u{1e921}', '\0', '\0']) ]; - } diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index 89894f7932..97df92a56d 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -81,8 +81,8 @@ PREAMBLE = """\ #![allow(missing_docs, non_upper_case_globals, non_snake_case, clippy::unreadable_literal)] -use crate::unicode::version::UnicodeVersion; use crate::unicode::bool_trie::{{BoolTrie, SmallBoolTrie}}; +use crate::unicode::version::UnicodeVersion; """.format(year=datetime.datetime.now().year) # Mapping taken from Table 12 from: @@ -555,6 +555,8 @@ def generate_table( if is_pub: pub_string = "pub " + yield "\n" + yield " #[rustfmt::skip]\n" yield " %sconst %s: %s = &[\n" % (pub_string, name, decl_type) data = [] @@ -568,7 +570,7 @@ def generate_table( for table_line in generate_table_lines("".join(data).split(","), 8): yield table_line - yield "\n ];\n\n" + yield "\n ];\n" def compute_trie(raw_data, chunk_size): @@ -634,6 +636,9 @@ def generate_bool_trie(name, codepoint_ranges, is_pub=False): pub_string = "" if is_pub: pub_string = "pub " + + yield "\n" + yield " #[rustfmt::skip]\n" yield " %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name) yield " r1: [\n" data = ("0x%016x" % chunk for chunk in chunks[:0x800 // chunk_size]) @@ -678,7 +683,7 @@ def generate_bool_trie(name, codepoint_ranges, is_pub=False): yield fragment yield "\n ],\n" - yield " };\n\n" + yield " };\n" def generate_small_bool_trie(name, codepoint_ranges, is_pub=False): @@ -700,6 +705,8 @@ def generate_small_bool_trie(name, codepoint_ranges, is_pub=False): if is_pub: pub_string = "pub " + yield "\n" + yield " #[rustfmt::skip]\n" yield (" %sconst %s: &super::SmallBoolTrie = &super::SmallBoolTrie {\n" % (pub_string, name)) @@ -717,7 +724,7 @@ def generate_small_bool_trie(name, codepoint_ranges, is_pub=False): yield fragment yield "\n ],\n" - yield " };\n\n" + yield " };\n" def generate_property_module(mod, grouped_categories, category_subset): @@ -726,7 +733,7 @@ def generate_property_module(mod, grouped_categories, category_subset): Generate Rust code for module defining properties. """ - yield "pub(crate) mod %s {\n" % mod + yield "pub(crate) mod %s {" % mod for cat in sorted(category_subset): if cat in ("Cc", "White_Space"): generator = generate_small_bool_trie("%s_table" % cat, grouped_categories[cat]) @@ -736,9 +743,10 @@ def generate_property_module(mod, grouped_categories, category_subset): for fragment in generator: yield fragment + yield "\n" yield " pub fn %s(c: char) -> bool {\n" % cat yield " %s_table.lookup(c)\n" % cat - yield " }\n\n" + yield " }\n" yield "}\n\n" @@ -753,21 +761,21 @@ def generate_conversions_module(unicode_data): yield """ pub fn to_lower(c: char) -> [char; 3] { match bsearch_case_table(c, to_lowercase_table) { - None => [c, '\\0', '\\0'], + None => [c, '\\0', '\\0'], Some(index) => to_lowercase_table[index].1, } } pub fn to_upper(c: char) -> [char; 3] { match bsearch_case_table(c, to_uppercase_table) { - None => [c, '\\0', '\\0'], + None => [c, '\\0', '\\0'], Some(index) => to_uppercase_table[index].1, } } fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option { table.binary_search_by(|&(key, _)| key.cmp(&c)).ok() - }\n\n""" + }\n""" decl_type = "&[(char, [char; 3])]" format_conversion = lambda x: "({},[{},{},{}])".format(*( @@ -827,13 +835,9 @@ def main(): /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of /// `char` and `str` methods are based on. #[unstable(feature = "unicode_version", issue = "49726")] - pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {{ - major: {version.major}, - minor: {version.minor}, - micro: {version.micro}, - _priv: (), - }}; - """).format(version=unicode_version) + pub const UNICODE_VERSION: UnicodeVersion = + UnicodeVersion {{ major: {v.major}, minor: {v.minor}, micro: {v.micro}, _priv: () }}; + """).format(v=unicode_version) buf.write(unicode_version_notice) get_path = lambda f: get_unicode_file_path(unicode_version, f) diff --git a/src/libcore/unit.rs b/src/libcore/unit.rs index bf01ceb8b2..f41f4a5e94 100644 --- a/src/libcore/unit.rs +++ b/src/libcore/unit.rs @@ -15,7 +15,7 @@ use crate::iter::FromIterator; /// ``` #[stable(feature = "unit_from_iter", since = "1.23.0")] impl FromIterator<()> for () { - fn from_iter>(iter: I) -> Self { + fn from_iter>(iter: I) -> Self { iter.into_iter().for_each(|()| {}) } } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index d22420e76d..2ecbe77072 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -11,6 +11,7 @@ #![feature(nll)] #![feature(rustc_private)] #![feature(unicode_internals)] +#![feature(bool_to_option)] pub use Piece::*; pub use Position::*; @@ -35,7 +36,7 @@ impl InnerOffset { /// A piece is a portion of the format string which represents the next part /// to emit. These are emitted as a stream by the `Parser` class. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Piece<'a> { /// A literal string which should directly be emitted String(&'a str), @@ -45,7 +46,7 @@ pub enum Piece<'a> { } /// Representation of an argument specification. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct Argument<'a> { /// Where to find this argument pub position: Position, @@ -54,7 +55,7 @@ pub struct Argument<'a> { } /// Specification for the formatting of an argument in the format string. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct FormatSpec<'a> { /// Optionally specified character to fill alignment with. pub fill: Option, @@ -74,10 +75,12 @@ pub struct FormatSpec<'a> { /// this argument, this can be empty or any number of characters, although /// it is required to be one word. pub ty: &'a str, + /// The span of the descriptor string (for diagnostics). + pub ty_span: Option, } /// Enum describing where an argument for a format can be located. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Position { /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), @@ -97,7 +100,7 @@ impl Position { } /// Enum of alignments which are supported. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Alignment { /// The value will be aligned to the left. AlignLeft, @@ -111,7 +114,7 @@ pub enum Alignment { /// Various flags which can be applied to format strings. The meaning of these /// flags is defined by the formatters themselves. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Flag { /// A `+` will be used to denote positive numbers. FlagSignPlus, @@ -131,7 +134,7 @@ pub enum Flag { /// A count is used for the precision and width parameters of an integer, and /// can reference either an argument or a literal integer. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Count { /// The count is specified explicitly. CountIs(usize), @@ -440,20 +443,9 @@ impl<'a> Parser<'a> { Some(ArgumentIs(i)) } else { match self.cur.peek() { - Some(&(_, c)) if c.is_alphabetic() => { + Some(&(_, c)) if rustc_lexer::is_id_start(c) => { Some(ArgumentNamed(Symbol::intern(self.word()))) } - Some(&(pos, c)) if c == '_' => { - let invalid_name = self.string(pos); - self.err_with_note(format!("invalid argument name `{}`", invalid_name), - "invalid argument name", - "argument names cannot start with an underscore", - self.to_span_index(pos).to( - self.to_span_index(pos + invalid_name.len()) - ), - ); - Some(ArgumentNamed(Symbol::intern(invalid_name))) - }, // This is an `ArgumentNext`. // Record the fact and do the resolution after parsing the @@ -475,6 +467,7 @@ impl<'a> Parser<'a> { width: CountImplied, width_span: None, ty: &self.input[..0], + ty_span: None, }; if !self.consume(':') { return spec; @@ -548,6 +541,7 @@ impl<'a> Parser<'a> { spec.precision_span = sp; } } + let ty_span_start = self.cur.peek().map(|(pos, _)| *pos); // Optional radix followed by the actual format specifier if self.consume('x') { if self.consume('?') { @@ -567,6 +561,12 @@ impl<'a> Parser<'a> { spec.ty = "?"; } else { spec.ty = self.word(); + let ty_span_end = self.cur.peek().map(|(pos, _)| *pos); + if !spec.ty.is_empty() { + spec.ty_span = ty_span_start + .and_then(|s| ty_span_end.map(|e| (s, e))) + .map(|(start, end)| self.to_span_index(start).to(self.to_span_index(end))); + } } spec } @@ -601,22 +601,34 @@ impl<'a> Parser<'a> { /// Rust identifier, except that it can't start with `_` character. fn word(&mut self) -> &'a str { let start = match self.cur.peek() { - Some(&(pos, c)) if c != '_' && rustc_lexer::is_id_start(c) => { + Some(&(pos, c)) if rustc_lexer::is_id_start(c) => { self.cur.next(); pos } _ => { - return &self.input[..0]; + return ""; } }; + let mut end = None; while let Some(&(pos, c)) = self.cur.peek() { if rustc_lexer::is_id_continue(c) { self.cur.next(); } else { - return &self.input[start..pos]; + end = Some(pos); + break; } } - &self.input[start..self.input.len()] + let end = end.unwrap_or(self.input.len()); + let word = &self.input[start..end]; + if word == "_" { + self.err_with_note( + "invalid argument name `_`", + "invalid argument name", + "argument name cannot be a single underscore", + self.to_span_index(start).to(self.to_span_index(end)), + ); + } + word } /// Optionally parses an integer at the current position. This doesn't deal @@ -633,11 +645,7 @@ impl<'a> Parser<'a> { break; } } - if found { - Some(cur) - } else { - None - } + found.then_some(cur) } } diff --git a/src/libfmt_macros/tests.rs b/src/libfmt_macros/tests.rs index e2ddb8810e..81359033ed 100644 --- a/src/libfmt_macros/tests.rs +++ b/src/libfmt_macros/tests.rs @@ -2,7 +2,7 @@ use super::*; fn same(fmt: &'static str, p: &[Piece<'static>]) { let parser = Parser::new(fmt, None, vec![], false); - assert!(parser.collect::>>() == p); + assert_eq!(parser.collect::>>(), p); } fn fmtdflt() -> FormatSpec<'static> { @@ -15,6 +15,7 @@ fn fmtdflt() -> FormatSpec<'static> { precision_span: None, width_span: None, ty: "", + ty_span: None, }; } @@ -82,7 +83,7 @@ fn format_position_nothing_else() { #[test] fn format_type() { same( - "{3:a}", + "{3:x}", &[NextArgument(Argument { position: ArgumentIs(3), format: FormatSpec { @@ -93,7 +94,8 @@ fn format_type() { width: CountImplied, precision_span: None, width_span: None, - ty: "a", + ty: "x", + ty_span: None, }, })]); } @@ -112,6 +114,7 @@ fn format_align_fill() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); same( @@ -127,6 +130,7 @@ fn format_align_fill() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); same( @@ -142,6 +146,7 @@ fn format_align_fill() { precision_span: None, width_span: None, ty: "abcd", + ty_span: Some(InnerSpan::new(6, 10)), }, })]); } @@ -150,7 +155,7 @@ fn format_counts() { use syntax_pos::{GLOBALS, Globals, edition}; GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || { same( - "{:10s}", + "{:10x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -161,11 +166,12 @@ fn format_counts() { width: CountIs(10), precision_span: None, width_span: None, - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:10$.10s}", + "{:10$.10x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -176,11 +182,12 @@ fn format_counts() { width: CountIsParam(10), precision_span: None, width_span: Some(InnerSpan::new(3, 6)), - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:.*s}", + "{:.*x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(1), format: FormatSpec { @@ -191,11 +198,12 @@ fn format_counts() { width: CountImplied, precision_span: Some(InnerSpan::new(3, 5)), width_span: None, - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:.10$s}", + "{:.10$x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -206,11 +214,12 @@ fn format_counts() { width: CountImplied, precision_span: Some(InnerSpan::new(3, 7)), width_span: None, - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:a$.b$s}", + "{:a$.b$?}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -221,7 +230,8 @@ fn format_counts() { width: CountIsName(Symbol::intern("a")), precision_span: None, width_span: None, - ty: "s", + ty: "?", + ty_span: None, }, })]); }); @@ -241,6 +251,7 @@ fn format_flags() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); same( @@ -256,13 +267,14 @@ fn format_flags() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); } #[test] fn format_mixture() { same( - "abcd {3:a} efg", + "abcd {3:x} efg", &[ String("abcd "), NextArgument(Argument { @@ -275,7 +287,8 @@ fn format_mixture() { width: CountImplied, precision_span: None, width_span: None, - ty: "a", + ty: "x", + ty_span: None, }, }), String(" efg"), diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs index 1e9e7e4b83..242eb6750b 100644 --- a/src/libpanic_unwind/dwarf/eh.rs +++ b/src/libpanic_unwind/dwarf/eh.rs @@ -130,7 +130,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>, foreign_e fn interpret_cs_action(cs_action: u64, lpad: usize, foreign_exception: bool) -> EHAction { if cs_action == 0 { // If cs_action is 0 then this is a cleanup (Drop::drop). We run these - // for both Rust panics and foriegn exceptions. + // for both Rust panics and foreign exceptions. EHAction::Cleanup(lpad) } else if foreign_exception { // catch_unwind should not catch foreign exceptions, only Rust panics. diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index d2a0ef7b1d..3a14197c77 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -91,5 +91,14 @@ pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8), #[unwind(allowed)] pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { let payload = payload as *mut &mut dyn BoxMeUp; - imp::panic(Box::from_raw((*payload).box_me_up())) + let payload = (*payload).take_box(); + + // Miri panic support: cfg'd out of normal builds just to be sure. + // When going through normal codegen, `miri_start_panic` is a NOP, so the + // Miri-enabled sysroot still supports normal unwinding. But when executed in + // Miri, this line initiates unwinding. + #[cfg(miri)] + core::intrinsics::miri_start_panic(payload); + + imp::panic(Box::from_raw(payload)) } diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 621813a2fe..ff9a215d33 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -98,9 +98,6 @@ use libc::{c_int, c_uint, c_void}; mod imp { pub type ptr_t = *mut u8; - #[cfg(bootstrap)] - pub const NAME1: [u8; 7] = [b'.', b'P', b'A', b'_', b'K', 0, 0]; - macro_rules! ptr { (0) => (core::ptr::null_mut()); ($e:expr) => ($e as *mut u8); @@ -112,9 +109,6 @@ mod imp { mod imp { pub type ptr_t = u32; - #[cfg(bootstrap)] - pub const NAME1: [u8; 7] = [b'.', b'P', b'E', b'A', b'_', b'K', 0]; - extern "C" { pub static __ImageBase: u8; } @@ -161,17 +155,11 @@ pub struct _PMD { pub struct _TypeDescriptor { pub pVFTable: *const u8, pub spare: *mut u8, - #[cfg(bootstrap)] - pub name: [u8; 7], - #[cfg(not(bootstrap))] pub name: [u8; 11], } // Note that we intentionally ignore name mangling rules here: we don't want C++ // to be able to catch Rust panics by simply declaring a `struct rust_panic`. -#[cfg(bootstrap)] -use imp::NAME1 as TYPE_NAME; -#[cfg(not(bootstrap))] const TYPE_NAME: [u8; 11] = *b"rust_panic\0"; static mut THROW_INFO: _ThrowInfo = _ThrowInfo { @@ -194,9 +182,6 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType { pdisp: -1, vdisp: 0, }, - #[cfg(bootstrap)] - sizeOrOffset: mem::size_of::<*mut u64>() as c_int, - #[cfg(not(bootstrap))] sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int, copy_function: ptr!(0), }; @@ -218,8 +203,7 @@ extern "C" { // an argument to the C++ personality function. // // Again, I'm not entirely sure what this is describing, it just seems to work. -#[cfg_attr(bootstrap, lang = "msvc_try_filter")] -#[cfg_attr(not(any(test, bootstrap)), lang = "eh_catch_typeinfo")] +#[cfg_attr(not(test), lang = "eh_catch_typeinfo")] static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, spare: core::ptr::null_mut(), @@ -238,12 +222,8 @@ pub unsafe fn panic(data: Box) -> u32 { // exception (constructed above). let ptrs = mem::transmute::<_, raw::TraitObject>(data); let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64]; - let mut ptrs_ptr = ptrs.as_mut_ptr(); - let throw_ptr = if cfg!(bootstrap) { - &mut ptrs_ptr as *mut _ as *mut _ - } else { - ptrs_ptr as *mut _ - }; + let ptrs_ptr = ptrs.as_mut_ptr(); + let throw_ptr = ptrs_ptr as *mut _; // This... may seems surprising, and justifiably so. On 32-bit MSVC the // pointers between these structure are just that, pointers. On 64-bit MSVC, diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 6166561d87..87cd8fcb14 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -25,7 +25,6 @@ #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(optin_builtin_traits)] -#![cfg_attr(bootstrap, feature(non_exhaustive))] #![feature(rustc_attrs)] #![feature(specialization)] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index de67f46eba..a4536bb6c4 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -10,10 +10,6 @@ path = "lib.rs" doctest = false [dependencies] -# Prevent cc from upgrading all the way to 1.0.46, -# which fails the build (see e.g. #65445.) -cc = "=1.0.37" - arena = { path = "../libarena" } bitflags = "1.2.1" fmt_macros = { path = "../libfmt_macros" } @@ -24,8 +20,9 @@ scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc-rayon = "0.3.0" rustc-rayon-core = "0.3.0" -polonius-engine = "0.10.0" +polonius-engine = "0.11.0" rustc_apfloat = { path = "../librustc_apfloat" } +rustc_feature = { path = "../librustc_feature" } rustc_target = { path = "../librustc_target" } rustc_macros = { path = "../librustc_macros" } rustc_data_structures = { path = "../librustc_data_structures" } @@ -39,5 +36,7 @@ parking_lot = "0.9" byteorder = { version = "1.3" } chalk-engine = { version = "0.9.0", default-features=false } rustc_fs_util = { path = "../librustc_fs_util" } -smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } -measureme = "0.4" +smallvec = { version = "1.0", features = ["union", "may_dangle"] } +measureme = "0.5" +rustc_error_codes = { path = "../librustc_error_codes" } +rustc_session = { path = "../librustc_session" } diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 3daf0fc9df..eb7a170980 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -23,17 +23,17 @@ macro_rules! arena_types { [] generics: rustc::ty::Generics, [] trait_def: rustc::ty::TraitDef, [] adt_def: rustc::ty::AdtDef, - [] steal_mir: rustc::ty::steal::Steal>, - [] mir: rustc::mir::Body<$tcx>, + [] steal_mir: rustc::ty::steal::Steal>, + [] mir: rustc::mir::BodyAndCache<$tcx>, [] steal_promoted: rustc::ty::steal::Steal< rustc_index::vec::IndexVec< rustc::mir::Promoted, - rustc::mir::Body<$tcx> + rustc::mir::BodyAndCache<$tcx> > >, [] promoted: rustc_index::vec::IndexVec< rustc::mir::Promoted, - rustc::mir::Body<$tcx> + rustc::mir::BodyAndCache<$tcx> >, [] tables: rustc::ty::TypeckTables<$tcx>, [] const_allocs: rustc::mir::interpret::Allocation, @@ -93,6 +93,7 @@ macro_rules! arena_types { rustc::hir::def_id::CrateNum > >, + [few] hir_forest: rustc::hir::map::Forest, [few] diagnostic_items: rustc_data_structures::fx::FxHashMap< syntax::symbol::Symbol, rustc::hir::def_id::DefId, @@ -100,7 +101,7 @@ macro_rules! arena_types { [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes, [few] lint_levels: rustc::lint::LintLevelMap, [few] stability_index: rustc::middle::stability::Index<'tcx>, - [few] features: syntax::feature_gate::Features, + [few] features: rustc_feature::Features, [few] all_traits: Vec, [few] privacy_access_levels: rustc::middle::privacy::AccessLevels, [few] target_features_whitelist: rustc_data_structures::fx::FxHashMap< @@ -304,7 +305,7 @@ impl DropArena { // Move the content to the arena by copying it and then forgetting // the content of the SmallVec vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); - mem::forget(vec.drain()); + mem::forget(vec.drain(..)); // Record the destructors after doing the allocation as that may panic // and would cause `object`'s destuctor to run twice if it was recorded before diff --git a/src/librustc/benches/dispatch.rs b/src/librustc/benches/dispatch.rs deleted file mode 100644 index e3b36be569..0000000000 --- a/src/librustc/benches/dispatch.rs +++ /dev/null @@ -1,34 +0,0 @@ -use test::Bencher; - -// Static/dynamic method dispatch - -struct Struct { - field: isize -} - -trait Trait { - fn method(&self) -> isize; -} - -impl Trait for Struct { - fn method(&self) -> isize { - self.field - } -} - -#[bench] -fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &Trait; - b.iter(|| { - t.method() - }); -} - -#[bench] -fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| { - s.method() - }); -} diff --git a/src/librustc/benches/lib.rs b/src/librustc/benches/lib.rs index 0f81586d3b..6b62402889 100644 --- a/src/librustc/benches/lib.rs +++ b/src/librustc/benches/lib.rs @@ -1,6 +1,63 @@ +#![feature(slice_patterns)] #![feature(test)] extern crate test; -mod dispatch; -mod pattern; +use test::Bencher; + +// Static/dynamic method dispatch + +struct Struct { + field: isize +} + +trait Trait { + fn method(&self) -> isize; +} + +impl Trait for Struct { + fn method(&self) -> isize { + self.field + } +} + +#[bench] +fn trait_vtable_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + let t = &s as &dyn Trait; + b.iter(|| { + t.method() + }); +} + +#[bench] +fn trait_static_method_call(b: &mut Bencher) { + let s = Struct { field: 10 }; + b.iter(|| { + s.method() + }); +} + +// Overhead of various match forms + +#[bench] +fn option_some(b: &mut Bencher) { + let x = Some(10); + b.iter(|| { + match x { + Some(y) => y, + None => 11 + } + }); +} + +#[bench] +fn vec_pattern(b: &mut Bencher) { + let x = [1,2,3,4,5,6]; + b.iter(|| { + match x { + [1,2,3,..] => 10, + _ => 11, + } + }); +} diff --git a/src/librustc/benches/pattern.rs b/src/librustc/benches/pattern.rs deleted file mode 100644 index fd8cc5b83f..0000000000 --- a/src/librustc/benches/pattern.rs +++ /dev/null @@ -1,25 +0,0 @@ -use test::Bencher; - -// Overhead of various match forms - -#[bench] -fn option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| { - match x { - Some(y) => y, - None => 11 - } - }); -} - -#[bench] -fn vec_pattern(b: &mut Bencher) { - let x = [1,2,3,4,5,6]; - b.iter(|| { - match x { - [1,2,3,..] => 10, - _ => 11, - } - }); -} diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index dea8d70aaf..17ab0c187a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -525,7 +525,7 @@ impl<'tcx> DepNodeParams<'tcx> for CrateNum { } fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - tcx.crate_name(*self).as_str().to_string() + tcx.crate_name(*self).to_string() } } @@ -578,7 +578,7 @@ impl<'tcx> DepNodeParams<'tcx> for HirId { /// the need to be mapped or unmapped. (This ensures we can serialize /// them even in the absence of a tcx.) #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, - RustcEncodable, RustcDecodable)] + RustcEncodable, RustcDecodable, HashStable)] pub struct WorkProductId { hash: Fingerprint } @@ -599,7 +599,3 @@ impl WorkProductId { } } } - -impl_stable_hash_for!(struct crate::dep_graph::WorkProductId { - hash -}); diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0104507f70..d952bf7ab9 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -710,14 +710,25 @@ impl DepGraph { return None } None => { - if !tcx.sess.has_errors() { + if !tcx.sess.has_errors_or_delayed_span_bugs() { bug!("try_mark_previous_green() - Forcing the DepNode \ should have set its color") } else { - // If the query we just forced has resulted - // in some kind of compilation error, we - // don't expect that the corresponding - // dep-node color has been updated. + // If the query we just forced has resulted in + // some kind of compilation error, we cannot rely on + // the dep-node color having been properly updated. + // This means that the query system has reached an + // invalid state. We let the compiler continue (by + // returning `None`) so it can emit error messages + // and wind down, but rely on the fact that this + // invalid state will not be persisted to the + // incremental compilation cache because of + // compilation errors being present. + debug!("try_mark_previous_green({:?}) - END - \ + dependency {:?} resulted in compilation error", + dep_node, + dep_dep_node); + return None } } } diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 43f3d7e89c..a1321d50f2 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -5,7 +5,6 @@ mod prev; mod query; mod safe; mod serialized; -pub mod cgu_reuse_tracker; pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, RecoverKey, label_strs}; pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result}; diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs deleted file mode 100644 index 3e35add961..0000000000 --- a/src/librustc/error_codes.rs +++ /dev/null @@ -1,2349 +0,0 @@ -// Error messages for EXXXX errors. -// Each message should start and end with a new line, and be wrapped to 80 -// characters. In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use -// `:set tw=0` to disable. -syntax::register_diagnostics! { -E0038: r##" -Trait objects like `Box` can only be constructed when certain -requirements are satisfied by the trait in question. - -Trait objects are a form of dynamic dispatch and use a dynamically sized type -for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a -type, as in `Box`, the inner type is 'unsized'. In such cases the boxed -pointer is a 'fat pointer' that contains an extra pointer to a table of methods -(among other things) for dynamic dispatch. This design mandates some -restrictions on the types of traits that are allowed to be used in trait -objects, which are collectively termed as 'object safety' rules. - -Attempting to create a trait object for a non object-safe trait will trigger -this error. - -There are various rules: - -### The trait cannot require `Self: Sized` - -When `Trait` is treated as a type, the type does not implement the special -`Sized` trait, because the type does not have a known size at compile time and -can only be accessed behind a pointer. Thus, if we have a trait like the -following: - -``` -trait Foo where Self: Sized { - -} -``` - -We cannot create an object of type `Box` or `&Foo` since in this case -`Self` would not be `Sized`. - -Generally, `Self: Sized` is used to indicate that the trait should not be used -as a trait object. If the trait comes from your own crate, consider removing -this restriction. - -### Method references the `Self` type in its parameters or return type - -This happens when a trait has a method like the following: - -``` -trait Trait { - fn foo(&self) -> Self; -} - -impl Trait for String { - fn foo(&self) -> Self { - "hi".to_owned() - } -} - -impl Trait for u8 { - fn foo(&self) -> Self { - 1 - } -} -``` - -(Note that `&self` and `&mut self` are okay, it's additional `Self` types which -cause this problem.) - -In such a case, the compiler cannot predict the return type of `foo()` in a -situation like the following: - -```compile_fail -trait Trait { - fn foo(&self) -> Self; -} - -fn call_foo(x: Box) { - let y = x.foo(); // What type is y? - // ... -} -``` - -If only some methods aren't object-safe, you can add a `where Self: Sized` bound -on them to mark them as explicitly unavailable to trait objects. The -functionality will still be available to all other implementers, including -`Box` which is itself sized (assuming you `impl Trait for Box`). - -``` -trait Trait { - fn foo(&self) -> Self where Self: Sized; - // more functions -} -``` - -Now, `foo()` can no longer be called on a trait object, but you will now be -allowed to make a trait object, and that will be able to call any object-safe -methods. With such a bound, one can still call `foo()` on types implementing -that trait that aren't behind trait objects. - -### Method has generic type parameters - -As mentioned before, trait objects contain pointers to method tables. So, if we -have: - -``` -trait Trait { - fn foo(&self); -} - -impl Trait for String { - fn foo(&self) { - // implementation 1 - } -} - -impl Trait for u8 { - fn foo(&self) { - // implementation 2 - } -} -// ... -``` - -At compile time each implementation of `Trait` will produce a table containing -the various methods (and other items) related to the implementation. - -This works fine, but when the method gains generic parameters, we can have a -problem. - -Usually, generic parameters get _monomorphized_. For example, if I have - -``` -fn foo(x: T) { - // ... -} -``` - -The machine code for `foo::()`, `foo::()`, `foo::()`, or any -other type substitution is different. Hence the compiler generates the -implementation on-demand. If you call `foo()` with a `bool` parameter, the -compiler will only generate code for `foo::()`. When we have additional -type parameters, the number of monomorphized implementations the compiler -generates does not grow drastically, since the compiler will only generate an -implementation if the function is called with unparametrized substitutions -(i.e., substitutions where none of the substituted types are themselves -parametrized). - -However, with trait objects we have to make a table containing _every_ object -that implements the trait. Now, if it has type parameters, we need to add -implementations for every type that implements the trait, and there could -theoretically be an infinite number of types. - -For example, with: - -``` -trait Trait { - fn foo(&self, on: T); - // more methods -} - -impl Trait for String { - fn foo(&self, on: T) { - // implementation 1 - } -} - -impl Trait for u8 { - fn foo(&self, on: T) { - // implementation 2 - } -} - -// 8 more implementations -``` - -Now, if we have the following code: - -```compile_fail,E0038 -# trait Trait { fn foo(&self, on: T); } -# impl Trait for String { fn foo(&self, on: T) {} } -# impl Trait for u8 { fn foo(&self, on: T) {} } -# impl Trait for bool { fn foo(&self, on: T) {} } -# // etc. -fn call_foo(thing: Box) { - thing.foo(true); // this could be any one of the 8 types above - thing.foo(1); - thing.foo("hello"); -} -``` - -We don't just need to create a table of all implementations of all methods of -`Trait`, we need to create such a table, for each different type fed to -`foo()`. In this case this turns out to be (10 types implementing `Trait`)*(3 -types being fed to `foo()`) = 30 implementations! - -With real world traits these numbers can grow drastically. - -To fix this, it is suggested to use a `where Self: Sized` bound similar to the -fix for the sub-error above if you do not intend to call the method with type -parameters: - -``` -trait Trait { - fn foo(&self, on: T) where Self: Sized; - // more methods -} -``` - -If this is not an option, consider replacing the type parameter with another -trait object (e.g., if `T: OtherTrait`, use `on: Box`). If the -number of types you intend to feed to this method is limited, consider manually -listing out the methods of different types. - -### Method has no receiver - -Methods that do not take a `self` parameter can't be called since there won't be -a way to get a pointer to the method table for them. - -``` -trait Foo { - fn foo() -> u8; -} -``` - -This could be called as `::foo()`, which would not be able to pick -an implementation. - -Adding a `Self: Sized` bound to these methods will generally make this compile. - -``` -trait Foo { - fn foo() -> u8 where Self: Sized; -} -``` - -### The trait cannot contain associated constants - -Just like static functions, associated constants aren't stored on the method -table. If the trait or any subtrait contain an associated constant, they cannot -be made into an object. - -```compile_fail,E0038 -trait Foo { - const X: i32; -} - -impl Foo {} -``` - -A simple workaround is to use a helper method instead: - -``` -trait Foo { - fn x(&self) -> i32; -} -``` - -### The trait cannot use `Self` as a type parameter in the supertrait listing - -This is similar to the second sub-error, but subtler. It happens in situations -like the following: - -```compile_fail,E0038 -trait Super {} - -trait Trait: Super { -} - -struct Foo; - -impl Super for Foo{} - -impl Trait for Foo {} - -fn main() { - let x: Box; -} -``` - -Here, the supertrait might have methods as follows: - -``` -trait Super { - fn get_a(&self) -> &A; // note that this is object safe! -} -``` - -If the trait `Trait` was deriving from something like `Super` or -`Super` (where `Foo` itself is `Foo`), this is okay, because given a type -`get_a()` will definitely return an object of that type. - -However, if it derives from `Super`, even though `Super` is object safe, -the method `get_a()` would return an object of unknown type when called on the -function. `Self` type parameters let us make object safe traits no longer safe, -so they are forbidden when specifying supertraits. - -There's no easy fix for this, generally code will need to be refactored so that -you no longer need to derive from `Super`. -"##, - -E0072: r##" -When defining a recursive struct or enum, any use of the type being defined -from inside the definition must occur behind a pointer (like `Box` or `&`). -This is because structs and enums must have a well-defined size, and without -the pointer, the size of the type would need to be unbounded. - -Consider the following erroneous definition of a type for a list of bytes: - -```compile_fail,E0072 -// error, invalid recursive struct type -struct ListNode { - head: u8, - tail: Option, -} -``` - -This type cannot have a well-defined size, because it needs to be arbitrarily -large (since we would be able to nest `ListNode`s to any depth). Specifically, - -```plain -size of `ListNode` = 1 byte for `head` - + 1 byte for the discriminant of the `Option` - + size of `ListNode` -``` - -One way to fix this is by wrapping `ListNode` in a `Box`, like so: - -``` -struct ListNode { - head: u8, - tail: Option>, -} -``` - -This works because `Box` is a pointer, so its size is well-known. -"##, - -E0080: r##" -This error indicates that the compiler was unable to sensibly evaluate an -constant expression that had to be evaluated. Attempting to divide by 0 -or causing integer overflow are two ways to induce this error. For example: - -```compile_fail,E0080 -enum Enum { - X = (1 << 500), - Y = (1 / 0) -} -``` - -Ensure that the expressions given can be evaluated as the desired integer type. -See the FFI section of the Reference for more information about using a custom -integer type: - -https://doc.rust-lang.org/reference.html#ffi-attributes -"##, - -E0106: r##" -This error indicates that a lifetime is missing from a type. If it is an error -inside a function signature, the problem may be with failing to adhere to the -lifetime elision rules (see below). - -Here are some simple examples of where you'll run into this error: - -```compile_fail,E0106 -struct Foo1 { x: &bool } - // ^ expected lifetime parameter -struct Foo2<'a> { x: &'a bool } // correct - -struct Bar1 { x: Foo2 } - // ^^^^ expected lifetime parameter -struct Bar2<'a> { x: Foo2<'a> } // correct - -enum Baz1 { A(u8), B(&bool), } - // ^ expected lifetime parameter -enum Baz2<'a> { A(u8), B(&'a bool), } // correct - -type MyStr1 = &str; - // ^ expected lifetime parameter -type MyStr2<'a> = &'a str; // correct -``` - -Lifetime elision is a special, limited kind of inference for lifetimes in -function signatures which allows you to leave out lifetimes in certain cases. -For more background on lifetime elision see [the book][book-le]. - -The lifetime elision rules require that any function signature with an elided -output lifetime must either have - - - exactly one input lifetime - - or, multiple input lifetimes, but the function must also be a method with a - `&self` or `&mut self` receiver - -In the first case, the output lifetime is inferred to be the same as the unique -input lifetime. In the second case, the lifetime is instead inferred to be the -same as the lifetime on `&self` or `&mut self`. - -Here are some examples of elision errors: - -```compile_fail,E0106 -// error, no input lifetimes -fn foo() -> &str { } - -// error, `x` and `y` have distinct lifetimes inferred -fn bar(x: &str, y: &str) -> &str { } - -// error, `y`'s lifetime is inferred to be distinct from `x`'s -fn baz<'a>(x: &'a str, y: &str) -> &str { } -``` - -[book-le]: https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision -"##, - -E0119: r##" -There are conflicting trait implementations for the same type. -Example of erroneous code: - -```compile_fail,E0119 -trait MyTrait { - fn get(&self) -> usize; -} - -impl MyTrait for T { - fn get(&self) -> usize { 0 } -} - -struct Foo { - value: usize -} - -impl MyTrait for Foo { // error: conflicting implementations of trait - // `MyTrait` for type `Foo` - fn get(&self) -> usize { self.value } -} -``` - -When looking for the implementation for the trait, the compiler finds -both the `impl MyTrait for T` where T is all types and the `impl -MyTrait for Foo`. Since a trait cannot be implemented multiple times, -this is an error. So, when you write: - -``` -trait MyTrait { - fn get(&self) -> usize; -} - -impl MyTrait for T { - fn get(&self) -> usize { 0 } -} -``` - -This makes the trait implemented on all types in the scope. So if you -try to implement it on another one after that, the implementations will -conflict. Example: - -``` -trait MyTrait { - fn get(&self) -> usize; -} - -impl MyTrait for T { - fn get(&self) -> usize { 0 } -} - -struct Foo; - -fn main() { - let f = Foo; - - f.get(); // the trait is implemented so we can use it -} -``` -"##, - -E0139: r##" -#### Note: this error code is no longer emitted by the compiler. - -There are various restrictions on transmuting between types in Rust; for example -types being transmuted must have the same size. To apply all these restrictions, -the compiler must know the exact types that may be transmuted. When type -parameters are involved, this cannot always be done. - -So, for example, the following is not allowed: - -``` -use std::mem::transmute; - -struct Foo(Vec); - -fn foo(x: Vec) { - // we are transmuting between Vec and Foo here - let y: Foo = unsafe { transmute(x) }; - // do something with y -} -``` - -In this specific case there's a good chance that the transmute is harmless (but -this is not guaranteed by Rust). However, when alignment and enum optimizations -come into the picture, it's quite likely that the sizes may or may not match -with different type parameter substitutions. It's not possible to check this for -_all_ possible types, so `transmute()` simply only accepts types without any -unsubstituted type parameters. - -If you need this, there's a good chance you're doing something wrong. Keep in -mind that Rust doesn't guarantee much about the layout of different structs -(even two structs with identical declarations may have different layouts). If -there is a solution that avoids the transmute entirely, try it instead. - -If it's possible, hand-monomorphize the code by writing the function for each -possible type substitution. It's possible to use traits to do this cleanly, -for example: - -``` -use std::mem::transmute; - -struct Foo(Vec); - -trait MyTransmutableType: Sized { - fn transmute(_: Vec) -> Foo; -} - -impl MyTransmutableType for u8 { - fn transmute(x: Vec) -> Foo { - unsafe { transmute(x) } - } -} - -impl MyTransmutableType for String { - fn transmute(x: Vec) -> Foo { - unsafe { transmute(x) } - } -} - -// ... more impls for the types you intend to transmute - -fn foo(x: Vec) { - let y: Foo = ::transmute(x); - // do something with y -} -``` - -Each impl will be checked for a size match in the transmute as usual, and since -there are no unbound type parameters involved, this should compile unless there -is a size mismatch in one of the impls. - -It is also possible to manually transmute: - -``` -# use std::ptr; -# let v = Some("value"); -# type SomeType = &'static [u8]; -unsafe { - ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType` -} -# ; -``` - -Note that this does not move `v` (unlike `transmute`), and may need a -call to `mem::forget(v)` in case you want to avoid destructors being called. -"##, - -E0152: r##" -A lang item was redefined. - -Erroneous code example: - -```compile_fail,E0152 -#![feature(lang_items)] - -#[lang = "arc"] -struct Foo; // error: duplicate lang item found: `arc` -``` - -Lang items are already implemented in the standard library. Unless you are -writing a free-standing application (e.g., a kernel), you do not need to provide -them yourself. - -You can build a free-standing crate by adding `#![no_std]` to the crate -attributes: - -```ignore (only-for-syntax-highlight) -#![no_std] -``` - -See also the [unstable book][1]. - -[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib -"##, - -E0214: r##" -A generic type was described using parentheses rather than angle brackets. -For example: - -```compile_fail,E0214 -fn main() { - let v: Vec(&str) = vec!["foo"]; -} -``` - -This is not currently supported: `v` should be defined as `Vec<&str>`. -Parentheses are currently only used with generic types when defining parameters -for `Fn`-family traits. -"##, - -E0230: r##" -The `#[rustc_on_unimplemented]` attribute lets you specify a custom error -message for when a particular trait isn't implemented on a type placed in a -position that needs that trait. For example, when the following code is -compiled: - -```compile_fail -#![feature(on_unimplemented)] - -fn foo>(x: T){} - -#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] -trait Index { /* ... */ } - -foo(true); // `bool` does not implement `Index` -``` - -There will be an error about `bool` not implementing `Index`, followed by a -note saying "the type `bool` cannot be indexed by `u8`". - -As you can see, you can specify type parameters in curly braces for -substitution with the actual types (using the regular format string syntax) in -a given situation. Furthermore, `{Self}` will substitute to the type (in this -case, `bool`) that we tried to use. - -This error appears when the curly braces contain an identifier which doesn't -match with any of the type parameters or the string `Self`. This might happen -if you misspelled a type parameter, or if you intended to use literal curly -braces. If it is the latter, escape the curly braces with a second curly brace -of the same type; e.g., a literal `{` is `{{`. -"##, - -E0231: r##" -The `#[rustc_on_unimplemented]` attribute lets you specify a custom error -message for when a particular trait isn't implemented on a type placed in a -position that needs that trait. For example, when the following code is -compiled: - -```compile_fail -#![feature(on_unimplemented)] - -fn foo>(x: T){} - -#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] -trait Index { /* ... */ } - -foo(true); // `bool` does not implement `Index` -``` - -there will be an error about `bool` not implementing `Index`, followed by a -note saying "the type `bool` cannot be indexed by `u8`". - -As you can see, you can specify type parameters in curly braces for -substitution with the actual types (using the regular format string syntax) in -a given situation. Furthermore, `{Self}` will substitute to the type (in this -case, `bool`) that we tried to use. - -This error appears when the curly braces do not contain an identifier. Please -add one of the same name as a type parameter. If you intended to use literal -braces, use `{{` and `}}` to escape them. -"##, - -E0232: r##" -The `#[rustc_on_unimplemented]` attribute lets you specify a custom error -message for when a particular trait isn't implemented on a type placed in a -position that needs that trait. For example, when the following code is -compiled: - -```compile_fail -#![feature(on_unimplemented)] - -fn foo>(x: T){} - -#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] -trait Index { /* ... */ } - -foo(true); // `bool` does not implement `Index` -``` - -there will be an error about `bool` not implementing `Index`, followed by a -note saying "the type `bool` cannot be indexed by `u8`". - -For this to work, some note must be specified. An empty attribute will not do -anything, please remove the attribute or add some helpful note for users of the -trait. -"##, - -E0261: r##" -When using a lifetime like `'a` in a type, it must be declared before being -used. - -These two examples illustrate the problem: - -```compile_fail,E0261 -// error, use of undeclared lifetime name `'a` -fn foo(x: &'a str) { } - -struct Foo { - // error, use of undeclared lifetime name `'a` - x: &'a str, -} -``` - -These can be fixed by declaring lifetime parameters: - -``` -struct Foo<'a> { - x: &'a str, -} - -fn foo<'a>(x: &'a str) {} -``` - -Impl blocks declare lifetime parameters separately. You need to add lifetime -parameters to an impl block if you're implementing a type that has a lifetime -parameter of its own. -For example: - -```compile_fail,E0261 -struct Foo<'a> { - x: &'a str, -} - -// error, use of undeclared lifetime name `'a` -impl Foo<'a> { - fn foo<'a>(x: &'a str) {} -} -``` - -This is fixed by declaring the impl block like this: - -``` -struct Foo<'a> { - x: &'a str, -} - -// correct -impl<'a> Foo<'a> { - fn foo(x: &'a str) {} -} -``` -"##, - -E0262: r##" -Declaring certain lifetime names in parameters is disallowed. For example, -because the `'static` lifetime is a special built-in lifetime name denoting -the lifetime of the entire program, this is an error: - -```compile_fail,E0262 -// error, invalid lifetime parameter name `'static` -fn foo<'static>(x: &'static str) { } -``` -"##, - -E0263: r##" -A lifetime name cannot be declared more than once in the same scope. For -example: - -```compile_fail,E0263 -// error, lifetime name `'a` declared twice in the same scope -fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { } -``` -"##, - -E0264: r##" -An unknown external lang item was used. Erroneous code example: - -```compile_fail,E0264 -#![feature(lang_items)] - -extern "C" { - #[lang = "cake"] // error: unknown external lang item: `cake` - fn cake(); -} -``` - -A list of available external lang items is available in -`src/librustc/middle/weak_lang_items.rs`. Example: - -``` -#![feature(lang_items)] - -extern "C" { - #[lang = "panic_impl"] // ok! - fn cake(); -} -``` -"##, - -E0271: r##" -This is because of a type mismatch between the associated type of some -trait (e.g., `T::Bar`, where `T` implements `trait Quux { type Bar; }`) -and another type `U` that is required to be equal to `T::Bar`, but is not. -Examples follow. - -Here is a basic example: - -```compile_fail,E0271 -trait Trait { type AssociatedType; } - -fn foo(t: T) where T: Trait { - println!("in foo"); -} - -impl Trait for i8 { type AssociatedType = &'static str; } - -foo(3_i8); -``` - -Here is that same example again, with some explanatory comments: - -```compile_fail,E0271 -trait Trait { type AssociatedType; } - -fn foo(t: T) where T: Trait { -// ~~~~~~~~ ~~~~~~~~~~~~~~~~~~ -// | | -// This says `foo` can | -// only be used with | -// some type that | -// implements `Trait`. | -// | -// This says not only must -// `T` be an impl of `Trait` -// but also that the impl -// must assign the type `u32` -// to the associated type. - println!("in foo"); -} - -impl Trait for i8 { type AssociatedType = &'static str; } -//~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// | | -// `i8` does have | -// implementation | -// of `Trait`... | -// ... but it is an implementation -// that assigns `&'static str` to -// the associated type. - -foo(3_i8); -// Here, we invoke `foo` with an `i8`, which does not satisfy -// the constraint `::AssociatedType=u32`, and -// therefore the type-checker complains with this error code. -``` - -To avoid those issues, you have to make the types match correctly. -So we can fix the previous examples like this: - -``` -// Basic Example: -trait Trait { type AssociatedType; } - -fn foo(t: T) where T: Trait { - println!("in foo"); -} - -impl Trait for i8 { type AssociatedType = &'static str; } - -foo(3_i8); - -// For-Loop Example: -let vs = vec![1, 2, 3, 4]; -for v in &vs { - match v { - &1 => {} - _ => {} - } -} -``` -"##, - - -E0275: r##" -This error occurs when there was a recursive trait requirement that overflowed -before it could be evaluated. Often this means that there is unbounded -recursion in resolving some type bounds. - -For example, in the following code: - -```compile_fail,E0275 -trait Foo {} - -struct Bar(T); - -impl Foo for T where Bar: Foo {} -``` - -To determine if a `T` is `Foo`, we need to check if `Bar` is `Foo`. However, -to do this check, we need to determine that `Bar>` is `Foo`. To -determine this, we check if `Bar>>` is `Foo`, and so on. This is -clearly a recursive requirement that can't be resolved directly. - -Consider changing your trait bounds so that they're less self-referential. -"##, - -E0276: r##" -This error occurs when a bound in an implementation of a trait does not match -the bounds specified in the original trait. For example: - -```compile_fail,E0276 -trait Foo { - fn foo(x: T); -} - -impl Foo for bool { - fn foo(x: T) where T: Copy {} -} -``` - -Here, all types implementing `Foo` must have a method `foo(x: T)` which can -take any type `T`. However, in the `impl` for `bool`, we have added an extra -bound that `T` is `Copy`, which isn't compatible with the original trait. - -Consider removing the bound from the method or adding the bound to the original -method definition in the trait. -"##, - -E0277: r##" -You tried to use a type which doesn't implement some trait in a place which -expected that trait. Erroneous code example: - -```compile_fail,E0277 -// here we declare the Foo trait with a bar method -trait Foo { - fn bar(&self); -} - -// we now declare a function which takes an object implementing the Foo trait -fn some_func(foo: T) { - foo.bar(); -} - -fn main() { - // we now call the method with the i32 type, which doesn't implement - // the Foo trait - some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied -} -``` - -In order to fix this error, verify that the type you're using does implement -the trait. Example: - -``` -trait Foo { - fn bar(&self); -} - -fn some_func(foo: T) { - foo.bar(); // we can now use this method since i32 implements the - // Foo trait -} - -// we implement the trait on the i32 type -impl Foo for i32 { - fn bar(&self) {} -} - -fn main() { - some_func(5i32); // ok! -} -``` - -Or in a generic context, an erroneous code example would look like: - -```compile_fail,E0277 -fn some_func(foo: T) { - println!("{:?}", foo); // error: the trait `core::fmt::Debug` is not - // implemented for the type `T` -} - -fn main() { - // We now call the method with the i32 type, - // which *does* implement the Debug trait. - some_func(5i32); -} -``` - -Note that the error here is in the definition of the generic function: Although -we only call it with a parameter that does implement `Debug`, the compiler -still rejects the function: It must work with all possible input types. In -order to make this example compile, we need to restrict the generic type we're -accepting: - -``` -use std::fmt; - -// Restrict the input type to types that implement Debug. -fn some_func(foo: T) { - println!("{:?}", foo); -} - -fn main() { - // Calling the method is still fine, as i32 implements Debug. - some_func(5i32); - - // This would fail to compile now: - // struct WithoutDebug; - // some_func(WithoutDebug); -} -``` - -Rust only looks at the signature of the called function, as such it must -already specify all requirements that will be used for every type parameter. -"##, - -E0281: r##" -#### Note: this error code is no longer emitted by the compiler. - -You tried to supply a type which doesn't implement some trait in a location -which expected that trait. This error typically occurs when working with -`Fn`-based types. Erroneous code example: - -```compile-fail -fn foo(x: F) { } - -fn main() { - // type mismatch: ... implements the trait `core::ops::Fn<(String,)>`, - // but the trait `core::ops::Fn<(usize,)>` is required - // [E0281] - foo(|y: String| { }); -} -``` - -The issue in this case is that `foo` is defined as accepting a `Fn` with one -argument of type `String`, but the closure we attempted to pass to it requires -one arguments of type `usize`. -"##, - -E0282: r##" -This error indicates that type inference did not result in one unique possible -type, and extra information is required. In most cases this can be provided -by adding a type annotation. Sometimes you need to specify a generic type -parameter manually. - -A common example is the `collect` method on `Iterator`. It has a generic type -parameter with a `FromIterator` bound, which for a `char` iterator is -implemented by `Vec` and `String` among others. Consider the following snippet -that reverses the characters of a string: - -```compile_fail,E0282 -let x = "hello".chars().rev().collect(); -``` - -In this case, the compiler cannot infer what the type of `x` should be: -`Vec` and `String` are both suitable candidates. To specify which type to -use, you can use a type annotation on `x`: - -``` -let x: Vec = "hello".chars().rev().collect(); -``` - -It is not necessary to annotate the full type. Once the ambiguity is resolved, -the compiler can infer the rest: - -``` -let x: Vec<_> = "hello".chars().rev().collect(); -``` - -Another way to provide the compiler with enough information, is to specify the -generic type parameter: - -``` -let x = "hello".chars().rev().collect::>(); -``` - -Again, you need not specify the full type if the compiler can infer it: - -``` -let x = "hello".chars().rev().collect::>(); -``` - -Apart from a method or function with a generic type parameter, this error can -occur when a type parameter of a struct or trait cannot be inferred. In that -case it is not always possible to use a type annotation, because all candidates -have the same return type. For instance: - -```compile_fail,E0282 -struct Foo { - num: T, -} - -impl Foo { - fn bar() -> i32 { - 0 - } - - fn baz() { - let number = Foo::bar(); - } -} -``` - -This will fail because the compiler does not know which instance of `Foo` to -call `bar` on. Change `Foo::bar()` to `Foo::::bar()` to resolve the error. -"##, - -E0283: r##" -This error occurs when the compiler doesn't have enough information -to unambiguously choose an implementation. - -For example: - -```compile_fail,E0283 -trait Generator { - fn create() -> u32; -} - -struct Impl; - -impl Generator for Impl { - fn create() -> u32 { 1 } -} - -struct AnotherImpl; - -impl Generator for AnotherImpl { - fn create() -> u32 { 2 } -} - -fn main() { - let cont: u32 = Generator::create(); - // error, impossible to choose one of Generator trait implementation - // Should it be Impl or AnotherImpl, maybe something else? -} -``` - -To resolve this error use the concrete type: - -``` -trait Generator { - fn create() -> u32; -} - -struct AnotherImpl; - -impl Generator for AnotherImpl { - fn create() -> u32 { 2 } -} - -fn main() { - let gen1 = AnotherImpl::create(); - - // if there are multiple methods with same name (different traits) - let gen2 = ::create(); -} -``` -"##, - -E0284: r##" -This error occurs when the compiler is unable to unambiguously infer the -return type of a function or method which is generic on return type, such -as the `collect` method for `Iterator`s. - -For example: - -```compile_fail,E0284 -fn foo() -> Result { - let results = [Ok(true), Ok(false), Err(())].iter().cloned(); - let v: Vec = results.collect()?; - // Do things with v... - Ok(true) -} -``` - -Here we have an iterator `results` over `Result`. -Hence, `results.collect()` can return any type implementing -`FromIterator>`. On the other hand, the -`?` operator can accept any type implementing `Try`. - -The author of this code probably wants `collect()` to return a -`Result, ()>`, but the compiler can't be sure -that there isn't another type `T` implementing both `Try` and -`FromIterator>` in scope such that -`T::Ok == Vec`. Hence, this code is ambiguous and an error -is returned. - -To resolve this error, use a concrete type for the intermediate expression: - -``` -fn foo() -> Result { - let results = [Ok(true), Ok(false), Err(())].iter().cloned(); - let v = { - let temp: Result, ()> = results.collect(); - temp? - }; - // Do things with v... - Ok(true) -} -``` - -Note that the type of `v` can now be inferred from the type of `temp`. -"##, - -E0308: r##" -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. - -For example: - -```compile_fail,E0308 -let x: i32 = "I am not a number!"; -// ~~~ ~~~~~~~~~~~~~~~~~~~~ -// | | -// | initializing expression; -// | compiler infers type `&str` -// | -// type `i32` assigned to variable `x` -``` -"##, - -E0309: r##" -The type definition contains some field whose type -requires an outlives annotation. Outlives annotations -(e.g., `T: 'a`) are used to guarantee that all the data in T is valid -for at least the lifetime `'a`. This scenario most commonly -arises when the type contains an associated type reference -like `>::Output`, as shown in this example: - -```compile_fail,E0309 -// This won't compile because the applicable impl of -// `SomeTrait` (below) requires that `T: 'a`, but the struct does -// not have a matching where-clause. -struct Foo<'a, T> { - foo: >::Output, -} - -trait SomeTrait<'a> { - type Output; -} - -impl<'a, T> SomeTrait<'a> for T -where - T: 'a, -{ - type Output = u32; -} -``` - -Here, the where clause `T: 'a` that appears on the impl is not known to be -satisfied on the struct. To make this example compile, you have to add -a where-clause like `T: 'a` to the struct definition: - -``` -struct Foo<'a, T> -where - T: 'a, -{ - foo: >::Output -} - -trait SomeTrait<'a> { - type Output; -} - -impl<'a, T> SomeTrait<'a> for T -where - T: 'a, -{ - type Output = u32; -} -``` -"##, - -E0310: r##" -Types in type definitions have lifetimes associated with them that represent -how long the data stored within them is guaranteed to be live. This lifetime -must be as long as the data needs to be alive, and missing the constraint that -denotes this will cause this error. - -```compile_fail,E0310 -// This won't compile because T is not constrained to the static lifetime -// the reference needs -struct Foo { - foo: &'static T -} -``` - -This will compile, because it has the constraint on the type parameter: - -``` -struct Foo { - foo: &'static T -} -``` -"##, - -E0312: r##" -Reference's lifetime of borrowed content doesn't match the expected lifetime. - -Erroneous code example: - -```compile_fail,E0312 -pub fn opt_str<'a>(maybestr: &'a Option) -> &'static str { - if maybestr.is_none() { - "(none)" - } else { - let s: &'a str = maybestr.as_ref().unwrap(); - s // Invalid lifetime! - } -} -``` - -To fix this error, either lessen the expected lifetime or find a way to not have -to use this reference outside of its current scope (by running the code directly -in the same block for example?): - -``` -// In this case, we can fix the issue by switching from "static" lifetime to 'a -pub fn opt_str<'a>(maybestr: &'a Option) -> &'a str { - if maybestr.is_none() { - "(none)" - } else { - let s: &'a str = maybestr.as_ref().unwrap(); - s // Ok! - } -} -``` -"##, - -E0317: r##" -This error occurs when an `if` expression without an `else` block is used in a -context where a type other than `()` is expected, for example a `let` -expression: - -```compile_fail,E0317 -fn main() { - let x = 5; - let a = if x == 5 { 1 }; -} -``` - -An `if` expression without an `else` block has the type `()`, so this is a type -error. To resolve it, add an `else` block having the same type as the `if` -block. -"##, - -E0391: r##" -This error indicates that some types or traits depend on each other -and therefore cannot be constructed. - -The following example contains a circular dependency between two traits: - -```compile_fail,E0391 -trait FirstTrait : SecondTrait { - -} - -trait SecondTrait : FirstTrait { - -} -``` -"##, - -E0398: r##" -#### Note: this error code is no longer emitted by the compiler. - -In Rust 1.3, the default object lifetime bounds are expected to change, as -described in [RFC 1156]. You are getting a warning because the compiler -thinks it is possible that this change will cause a compilation error in your -code. It is possible, though unlikely, that this is a false alarm. - -The heart of the change is that where `&'a Box` used to default to -`&'a Box`, it now defaults to `&'a Box` (here, -`SomeTrait` is the name of some trait type). Note that the only types which are -affected are references to boxes, like `&Box` or -`&[Box]`. More common types like `&SomeTrait` or `Box` -are unaffected. - -To silence this warning, edit your code to use an explicit bound. Most of the -time, this means that you will want to change the signature of a function that -you are calling. For example, if the error is reported on a call like `foo(x)`, -and `foo` is defined as follows: - -``` -# trait SomeTrait {} -fn foo(arg: &Box) { /* ... */ } -``` - -You might change it to: - -``` -# trait SomeTrait {} -fn foo<'a>(arg: &'a Box) { /* ... */ } -``` - -This explicitly states that you expect the trait object `SomeTrait` to contain -references (with a maximum lifetime of `'a`). - -[RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md -"##, - -E0452: r##" -An invalid lint attribute has been given. Erroneous code example: - -```compile_fail,E0452 -#![allow(foo = "")] // error: malformed lint attribute -``` - -Lint attributes only accept a list of identifiers (where each identifier is a -lint name). Ensure the attribute is of this form: - -``` -#![allow(foo)] // ok! -// or: -#![allow(foo, foo2)] // ok! -``` -"##, - -E0453: r##" -A lint check attribute was overruled by a `forbid` directive set as an -attribute on an enclosing scope, or on the command line with the `-F` option. - -Example of erroneous code: - -```compile_fail,E0453 -#![forbid(non_snake_case)] - -#[allow(non_snake_case)] -fn main() { - let MyNumber = 2; // error: allow(non_snake_case) overruled by outer - // forbid(non_snake_case) -} -``` - -The `forbid` lint setting, like `deny`, turns the corresponding compiler -warning into a hard error. Unlike `deny`, `forbid` prevents itself from being -overridden by inner attributes. - -If you're sure you want to override the lint check, you can change `forbid` to -`deny` (or use `-D` instead of `-F` if the `forbid` setting was given as a -command-line option) to allow the inner lint check attribute: - -``` -#![deny(non_snake_case)] - -#[allow(non_snake_case)] -fn main() { - let MyNumber = 2; // ok! -} -``` - -Otherwise, edit the code to pass the lint check, and remove the overruled -attribute: - -``` -#![forbid(non_snake_case)] - -fn main() { - let my_number = 2; -} -``` -"##, - -E0478: r##" -A lifetime bound was not satisfied. - -Erroneous code example: - -```compile_fail,E0478 -// Check that the explicit lifetime bound (`'SnowWhite`, in this example) must -// outlive all the superbounds from the trait (`'kiss`, in this example). - -trait Wedding<'t>: 't { } - -struct Prince<'kiss, 'SnowWhite> { - child: Box + 'SnowWhite>, - // error: lifetime bound not satisfied -} -``` - -In this example, the `'SnowWhite` lifetime is supposed to outlive the `'kiss` -lifetime but the declaration of the `Prince` struct doesn't enforce it. To fix -this issue, you need to specify it: - -``` -trait Wedding<'t>: 't { } - -struct Prince<'kiss, 'SnowWhite: 'kiss> { // You say here that 'kiss must live - // longer than 'SnowWhite. - child: Box + 'SnowWhite>, // And now it's all good! -} -``` -"##, - -E0491: r##" -A reference has a longer lifetime than the data it references. - -Erroneous code example: - -```compile_fail,E0491 -trait SomeTrait<'a> { - type Output; -} - -impl<'a, T> SomeTrait<'a> for T { - type Output = &'a T; // compile error E0491 -} -``` - -Here, the problem is that a reference type like `&'a T` is only valid -if all the data in T outlives the lifetime `'a`. But this impl as written -is applicable to any lifetime `'a` and any type `T` -- we have no guarantee -that `T` outlives `'a`. To fix this, you can add a where clause like -`where T: 'a`. - -``` -trait SomeTrait<'a> { - type Output; -} - -impl<'a, T> SomeTrait<'a> for T -where - T: 'a, -{ - type Output = &'a T; // compile error E0491 -} -``` -"##, - -E0495: r##" -A lifetime cannot be determined in the given situation. - -Erroneous code example: - -```compile_fail,E0495 -fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { - match (&t,) { // error! - ((u,),) => u, - } -} - -let y = Box::new((42,)); -let x = transmute_lifetime(&y); -``` - -In this code, you have two ways to solve this issue: - 1. Enforce that `'a` lives at least as long as `'b`. - 2. Use the same lifetime requirement for both input and output values. - -So for the first solution, you can do it by replacing `'a` with `'a: 'b`: - -``` -fn transmute_lifetime<'a: 'b, 'b, T>(t: &'a (T,)) -> &'b T { - match (&t,) { // ok! - ((u,),) => u, - } -} -``` - -In the second you can do it by simply removing `'b` so they both use `'a`: - -``` -fn transmute_lifetime<'a, T>(t: &'a (T,)) -> &'a T { - match (&t,) { // ok! - ((u,),) => u, - } -} -``` -"##, - -E0496: r##" -A lifetime name is shadowing another lifetime name. - -Erroneous code example: - -```compile_fail,E0496 -struct Foo<'a> { - a: &'a i32, -} - -impl<'a> Foo<'a> { - fn f<'a>(x: &'a i32) { // error: lifetime name `'a` shadows a lifetime - // name that is already in scope - } -} -``` - -Please change the name of one of the lifetimes to remove this error. Example: - -``` -struct Foo<'a> { - a: &'a i32, -} - -impl<'a> Foo<'a> { - fn f<'b>(x: &'b i32) { // ok! - } -} - -fn main() { -} -``` -"##, - -E0497: r##" -#### Note: this error code is no longer emitted by the compiler. - -A stability attribute was used outside of the standard library. - -Erroneous code example: - -```compile_fail -#[stable] // error: stability attributes may not be used outside of the - // standard library -fn foo() {} -``` - -It is not possible to use stability attributes outside of the standard library. -Also, for now, it is not possible to write deprecation messages either. -"##, - -E0517: r##" -This error indicates that a `#[repr(..)]` attribute was placed on an -unsupported item. - -Examples of erroneous code: - -```compile_fail,E0517 -#[repr(C)] -type Foo = u8; - -#[repr(packed)] -enum Foo {Bar, Baz} - -#[repr(u8)] -struct Foo {bar: bool, baz: bool} - -#[repr(C)] -impl Foo { - // ... -} -``` - -* The `#[repr(C)]` attribute can only be placed on structs and enums. -* The `#[repr(packed)]` and `#[repr(simd)]` attributes only work on structs. -* The `#[repr(u8)]`, `#[repr(i16)]`, etc attributes only work on enums. - -These attributes do not work on typedefs, since typedefs are just aliases. - -Representations like `#[repr(u8)]`, `#[repr(i64)]` are for selecting the -discriminant size for enums with no data fields on any of the variants, e.g. -`enum Color {Red, Blue, Green}`, effectively setting the size of the enum to -the size of the provided type. Such an enum can be cast to a value of the same -type as well. In short, `#[repr(u8)]` makes the enum behave like an integer -with a constrained set of allowed values. - -Only field-less enums can be cast to numerical primitives, so this attribute -will not apply to structs. - -`#[repr(packed)]` reduces padding to make the struct size smaller. The -representation of enums isn't strictly defined in Rust, and this attribute -won't work on enums. - -`#[repr(simd)]` will give a struct consisting of a homogeneous series of machine -types (i.e., `u8`, `i32`, etc) a representation that permits vectorization via -SIMD. This doesn't make much sense for enums since they don't consist of a -single list of data. -"##, - -E0518: r##" -This error indicates that an `#[inline(..)]` attribute was incorrectly placed -on something other than a function or method. - -Examples of erroneous code: - -```compile_fail,E0518 -#[inline(always)] -struct Foo; - -#[inline(never)] -impl Foo { - // ... -} -``` - -`#[inline]` hints the compiler whether or not to attempt to inline a method or -function. By default, the compiler does a pretty good job of figuring this out -itself, but if you feel the need for annotations, `#[inline(always)]` and -`#[inline(never)]` can override or force the compiler's decision. - -If you wish to apply this attribute to all methods in an impl, manually annotate -each method; it is not possible to annotate the entire impl with an `#[inline]` -attribute. -"##, - -E0522: r##" -The lang attribute is intended for marking special items that are built-in to -Rust itself. This includes special traits (like `Copy` and `Sized`) that affect -how the compiler behaves, as well as special functions that may be automatically -invoked (such as the handler for out-of-bounds accesses when indexing a slice). -Erroneous code example: - -```compile_fail,E0522 -#![feature(lang_items)] - -#[lang = "cookie"] -fn cookie() -> ! { // error: definition of an unknown language item: `cookie` - loop {} -} -``` -"##, - -E0525: r##" -A closure was used but didn't implement the expected trait. - -Erroneous code example: - -```compile_fail,E0525 -struct X; - -fn foo(_: T) {} -fn bar(_: T) {} - -fn main() { - let x = X; - let closure = |_| foo(x); // error: expected a closure that implements - // the `Fn` trait, but this closure only - // implements `FnOnce` - bar(closure); -} -``` - -In the example above, `closure` is an `FnOnce` closure whereas the `bar` -function expected an `Fn` closure. In this case, it's simple to fix the issue, -you just have to implement `Copy` and `Clone` traits on `struct X` and it'll -be ok: - -``` -#[derive(Clone, Copy)] // We implement `Clone` and `Copy` traits. -struct X; - -fn foo(_: T) {} -fn bar(_: T) {} - -fn main() { - let x = X; - let closure = |_| foo(x); - bar(closure); // ok! -} -``` - -To understand better how closures work in Rust, read: -https://doc.rust-lang.org/book/ch13-01-closures.html -"##, - -E0566: r##" -Conflicting representation hints have been used on a same item. - -Erroneous code example: - -``` -#[repr(u32, u64)] // warning! -enum Repr { A } -``` - -In most cases (if not all), using just one representation hint is more than -enough. If you want to have a representation hint depending on the current -architecture, use `cfg_attr`. Example: - -``` -#[cfg_attr(linux, repr(u32))] -#[cfg_attr(not(linux), repr(u64))] -enum Repr { A } -``` -"##, - -E0580: r##" -The `main` function was incorrectly declared. - -Erroneous code example: - -```compile_fail,E0580 -fn main(x: i32) { // error: main function has wrong type - println!("{}", x); -} -``` - -The `main` function prototype should never take arguments. -Example: - -``` -fn main() { - // your code -} -``` - -If you want to get command-line arguments, use `std::env::args`. To exit with a -specified exit code, use `std::process::exit`. -"##, - -E0562: r##" -Abstract return types (written `impl Trait` for some trait `Trait`) are only -allowed as function and inherent impl return types. - -Erroneous code example: - -```compile_fail,E0562 -fn main() { - let count_to_ten: impl Iterator = 0..10; - // error: `impl Trait` not allowed outside of function and inherent method - // return types - for i in count_to_ten { - println!("{}", i); - } -} -``` - -Make sure `impl Trait` only appears in return-type position. - -``` -fn count_to_n(n: usize) -> impl Iterator { - 0..n -} - -fn main() { - for i in count_to_n(10) { // ok! - println!("{}", i); - } -} -``` - -See [RFC 1522] for more details. - -[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md -"##, - -E0593: r##" -You tried to supply an `Fn`-based type with an incorrect number of arguments -than what was expected. - -Erroneous code example: - -```compile_fail,E0593 -fn foo(x: F) { } - -fn main() { - // [E0593] closure takes 1 argument but 0 arguments are required - foo(|y| { }); -} -``` -"##, - -E0602: r##" -An unknown lint was used on the command line. - -Erroneous example: - -```sh -rustc -D bogus omse_file.rs -``` - -Maybe you just misspelled the lint name or the lint doesn't exist anymore. -Either way, try to update/remove it in order to fix the error. -"##, - -E0621: r##" -This error code indicates a mismatch between the lifetimes appearing in the -function signature (i.e., the parameter types and the return type) and the -data-flow found in the function body. - -Erroneous code example: - -```compile_fail,E0621 -fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // error: explicit lifetime - // required in the type of - // `y` - if x > y { x } else { y } -} -``` - -In the code above, the function is returning data borrowed from either `x` or -`y`, but the `'a` annotation indicates that it is returning data only from `x`. -To fix the error, the signature and the body must be made to match. Typically, -this is done by updating the function signature. So, in this case, we change -the type of `y` to `&'a i32`, like so: - -``` -fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - if x > y { x } else { y } -} -``` - -Now the signature indicates that the function data borrowed from either `x` or -`y`. Alternatively, you could change the body to not return data from `y`: - -``` -fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { - x -} -``` -"##, - -E0635: r##" -The `#![feature]` attribute specified an unknown feature. - -Erroneous code example: - -```compile_fail,E0635 -#![feature(nonexistent_rust_feature)] // error: unknown feature -``` - -"##, - -E0636: r##" -A `#![feature]` attribute was declared multiple times. - -Erroneous code example: - -```compile_fail,E0636 -#![allow(stable_features)] -#![feature(rust1)] -#![feature(rust1)] // error: the feature `rust1` has already been declared -``` - -"##, - -E0644: r##" -A closure or generator was constructed that references its own type. - -Erroneous example: - -```compile-fail,E0644 -fn fix(f: &F) - where F: Fn(&F) -{ - f(&f); -} - -fn main() { - fix(&|y| { - // Here, when `x` is called, the parameter `y` is equal to `x`. - }); -} -``` - -Rust does not permit a closure to directly reference its own type, -either through an argument (as in the example above) or by capturing -itself through its environment. This restriction helps keep closure -inference tractable. - -The easiest fix is to rewrite your closure into a top-level function, -or into a method. In some cases, you may also be able to have your -closure call itself by capturing a `&Fn()` object or `fn()` pointer -that refers to itself. That is permitting, since the closure would be -invoking itself via a virtual call, and hence does not directly -reference its own *type*. - -"##, - -E0692: r##" -A `repr(transparent)` type was also annotated with other, incompatible -representation hints. - -Erroneous code example: - -```compile_fail,E0692 -#[repr(transparent, C)] // error: incompatible representation hints -struct Grams(f32); -``` - -A type annotated as `repr(transparent)` delegates all representation concerns to -another type, so adding more representation hints is contradictory. Remove -either the `transparent` hint or the other hints, like this: - -``` -#[repr(transparent)] -struct Grams(f32); -``` - -Alternatively, move the other attributes to the contained type: - -``` -#[repr(C)] -struct Foo { - x: i32, - // ... -} - -#[repr(transparent)] -struct FooWrapper(Foo); -``` - -Note that introducing another `struct` just to have a place for the other -attributes may have unintended side effects on the representation: - -``` -#[repr(transparent)] -struct Grams(f32); - -#[repr(C)] -struct Float(f32); - -#[repr(transparent)] -struct Grams2(Float); // this is not equivalent to `Grams` above -``` - -Here, `Grams2` is a not equivalent to `Grams` -- the former transparently wraps -a (non-transparent) struct containing a single float, while `Grams` is a -transparent wrapper around a float. This can make a difference for the ABI. -"##, - -E0697: r##" -A closure has been used as `static`. - -Erroneous code example: - -```compile_fail,E0697 -fn main() { - static || {}; // used as `static` -} -``` - -Closures cannot be used as `static`. They "save" the environment, -and as such a static closure would save only a static environment -which would consist only of variables with a static lifetime. Given -this it would be better to use a proper function. The easiest fix -is to remove the `static` keyword. -"##, - -E0698: r##" -When using generators (or async) all type variables must be bound so a -generator can be constructed. - -Erroneous code example: - -```edition2018,compile-fail,E0698 -async fn bar() -> () {} - -async fn foo() { - bar().await; // error: cannot infer type for `T` -} -``` - -In the above example `T` is unknowable by the compiler. -To fix this you must bind `T` to a concrete type such as `String` -so that a generator can then be constructed: - -```edition2018 -async fn bar() -> () {} - -async fn foo() { - bar::().await; - // ^^^^^^^^ specify type explicitly -} -``` -"##, - -E0700: r##" -The `impl Trait` return type captures lifetime parameters that do not -appear within the `impl Trait` itself. - -Erroneous code example: - -```compile-fail,E0700 -use std::cell::Cell; - -trait Trait<'a> { } - -impl<'a, 'b> Trait<'b> for Cell<&'a u32> { } - -fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> -where 'x: 'y -{ - x -} -``` - -Here, the function `foo` returns a value of type `Cell<&'x u32>`, -which references the lifetime `'x`. However, the return type is -declared as `impl Trait<'y>` -- this indicates that `foo` returns -"some type that implements `Trait<'y>`", but it also indicates that -the return type **only captures data referencing the lifetime `'y`**. -In this case, though, we are referencing data with lifetime `'x`, so -this function is in error. - -To fix this, you must reference the lifetime `'x` from the return -type. For example, changing the return type to `impl Trait<'y> + 'x` -would work: - -``` -use std::cell::Cell; - -trait Trait<'a> { } - -impl<'a,'b> Trait<'b> for Cell<&'a u32> { } - -fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x -where 'x: 'y -{ - x -} -``` -"##, - -E0701: r##" -This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed -on something other than a struct or enum. - -Examples of erroneous code: - -```compile_fail,E0701 -#[non_exhaustive] -trait Foo { } -``` -"##, - -E0718: r##" -This error indicates that a `#[lang = ".."]` attribute was placed -on the wrong type of item. - -Examples of erroneous code: - -```compile_fail,E0718 -#![feature(lang_items)] - -#[lang = "arc"] -static X: u32 = 42; -``` -"##, - -E0728: r##" -[`await`] has been used outside [`async`] function or block. - -Erroneous code examples: - -```edition2018,compile_fail,E0728 -# use std::pin::Pin; -# use std::future::Future; -# use std::task::{Context, Poll}; -# -# struct WakeOnceThenComplete(bool); -# -# fn wake_and_yield_once() -> WakeOnceThenComplete { -# WakeOnceThenComplete(false) -# } -# -# impl Future for WakeOnceThenComplete { -# type Output = (); -# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { -# if self.0 { -# Poll::Ready(()) -# } else { -# cx.waker().wake_by_ref(); -# self.0 = true; -# Poll::Pending -# } -# } -# } -# -fn foo() { - wake_and_yield_once().await // `await` is used outside `async` context -} -``` - -[`await`] is used to suspend the current computation until the given -future is ready to produce a value. So it is legal only within -an [`async`] context, like an `async fn` or an `async` block. - -```edition2018 -# use std::pin::Pin; -# use std::future::Future; -# use std::task::{Context, Poll}; -# -# struct WakeOnceThenComplete(bool); -# -# fn wake_and_yield_once() -> WakeOnceThenComplete { -# WakeOnceThenComplete(false) -# } -# -# impl Future for WakeOnceThenComplete { -# type Output = (); -# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { -# if self.0 { -# Poll::Ready(()) -# } else { -# cx.waker().wake_by_ref(); -# self.0 = true; -# Poll::Pending -# } -# } -# } -# -async fn foo() { - wake_and_yield_once().await // `await` is used within `async` function -} - -fn bar(x: u8) -> impl Future { - async move { - wake_and_yield_once().await; // `await` is used within `async` block - x - } -} -``` - -[`async`]: https://doc.rust-lang.org/std/keyword.async.html -[`await`]: https://doc.rust-lang.org/std/keyword.await.html -"##, - -E0734: r##" -A stability attribute has been used outside of the standard library. - -Erroneous code examples: - -```compile_fail,E0734 -#[rustc_deprecated(since = "b", reason = "text")] // invalid -#[stable(feature = "a", since = "b")] // invalid -#[unstable(feature = "b", issue = "0")] // invalid -fn foo(){} -``` - -These attributes are meant to only be used by the standard library and are -rejected in your own crates. -"##, - -E0736: r##" -`#[track_caller]` and `#[naked]` cannot both be applied to the same function. - -Erroneous code example: - -```compile_fail,E0736 -#![feature(track_caller)] - -#[naked] -#[track_caller] -fn foo() {} -``` - -This is primarily due to ABI incompatibilities between the two attributes. -See [RFC 2091] for details on this and other limitations. - -[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md -"##, - -E0738: r##" -`#[track_caller]` cannot be used in traits yet. This is due to limitations in -the compiler which are likely to be temporary. See [RFC 2091] for details on -this and other restrictions. - -Erroneous example with a trait method implementation: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { - fn bar(&self); -} - -impl Foo for u64 { - #[track_caller] - fn bar(&self) {} -} -``` - -Erroneous example with a blanket trait method implementation: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { - #[track_caller] - fn bar(&self) {} - fn baz(&self); -} -``` - -Erroneous example with a trait method declaration: - -```compile_fail,E0738 -#![feature(track_caller)] - -trait Foo { - fn bar(&self) {} - - #[track_caller] - fn baz(&self); -} -``` - -Note that while the compiler may be able to support the attribute in traits in -the future, [RFC 2091] prohibits their implementation without a follow-up RFC. - -[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md -"##, - -; -// E0006, // merged with E0005 -// E0101, // replaced with E0282 -// E0102, // replaced with E0282 -// E0134, -// E0135, -// E0272, // on_unimplemented #0 -// E0273, // on_unimplemented #1 -// E0274, // on_unimplemented #2 -// E0278, // requirement is not satisfied - E0279, // requirement is not satisfied - E0280, // requirement is not satisfied -// E0285, // overflow evaluation builtin bounds -// E0296, // replaced with a generic attribute input check -// E0300, // unexpanded macro -// E0304, // expected signed integer constant -// E0305, // expected constant - E0311, // thing may not live long enough - E0313, // lifetime of borrowed pointer outlives lifetime of captured - // variable - E0314, // closure outlives stack frame - E0315, // cannot invoke closure outside of its lifetime - E0316, // nested quantification of lifetimes - E0320, // recursive overflow during dropck - E0473, // dereference of reference outside its lifetime - E0474, // captured variable `..` does not outlive the enclosing closure - E0475, // index of slice outside its lifetime - E0476, // lifetime of the source pointer does not outlive lifetime bound... - E0477, // the type `..` does not fulfill the required lifetime... - E0479, // the type `..` (provided as the value of a type parameter) is... - E0480, // lifetime of method receiver does not outlive the method call - E0481, // lifetime of function argument does not outlive the function call - E0482, // lifetime of return value does not outlive the function call - E0483, // lifetime of operand does not outlive the operation - E0484, // reference is not valid at the time of borrow - E0485, // automatically reference is not valid at the time of borrow - E0486, // type of expression contains references that are not valid during.. - E0487, // unsafe use of destructor: destructor might be called while... - E0488, // lifetime of variable does not enclose its declaration - E0489, // type/lifetime parameter not in scope here - E0490, // a value of type `..` is borrowed for too long - E0623, // lifetime mismatch where both parameters are anonymous regions - E0628, // generators cannot have explicit parameters - E0631, // type mismatch in closure arguments - E0637, // "'_" is not a valid lifetime bound - E0657, // `impl Trait` can only capture lifetimes bound at the fn level - E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax - E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders -// E0707, // multiple elided lifetimes used in arguments of `async fn` - E0708, // `async` non-`move` closures with parameters are not currently - // supported -// E0709, // multiple different lifetimes used in arguments of `async fn` - E0710, // an unknown tool name found in scoped lint - E0711, // a feature has been declared with conflicting stability attributes -// E0702, // replaced with a generic attribute input check - E0726, // non-explicit (not `'_`) elided lifetime in unsupported position - E0727, // `async` generators are not yet supported - E0739, // invalid track_caller application/syntax -} diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 96562002aa..ea1c585176 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -16,6 +16,8 @@ use std::fmt::{self, Display}; use syntax::{attr, symbol::sym}; use syntax_pos::Span; +use rustc_error_codes::*; + #[derive(Copy, Clone, PartialEq)] pub(crate) enum MethodKind { Trait { body: bool }, diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index d4d7af92fe..231b054f97 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -40,10 +40,8 @@ pub enum NonMacroAttrKind { Tool, /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`). DeriveHelper, - /// Single-segment custom attribute registered by a legacy plugin (`register_attribute`). - LegacyPluginHelper, - /// Single-segment custom attribute not registered in any way (`#[my_attr]`). - Custom, + /// Single-segment custom attribute registered with `#[register_attr]`. + Registered, } #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] @@ -129,6 +127,34 @@ impl DefKind { _ => "a", } } + + pub fn matches_ns(&self, ns: Namespace) -> bool { + match self { + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::OpaqueTy + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::AssocOpaqueTy + | DefKind::TyParam => ns == Namespace::TypeNS, + + DefKind::Fn + | DefKind::Const + | DefKind::ConstParam + | DefKind::Static + | DefKind::Ctor(..) + | DefKind::Method + | DefKind::AssocConst => ns == Namespace::ValueNS, + + DefKind::Macro(..) => ns == Namespace::MacroNS, + } + } } #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] @@ -329,8 +355,22 @@ impl NonMacroAttrKind { NonMacroAttrKind::Builtin => "built-in attribute", NonMacroAttrKind::Tool => "tool attribute", NonMacroAttrKind::DeriveHelper => "derive helper attribute", - NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute", - NonMacroAttrKind::Custom => "custom attribute", + NonMacroAttrKind::Registered => "explicitly registered attribute", + } + } + + pub fn article(self) -> &'static str { + match self { + NonMacroAttrKind::Registered => "an", + _ => "a", + } + } + + /// Users of some attributes cannot mark them as used, so they are considered always used. + pub fn is_used(self) -> bool { + match self { + NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true, + NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false, } } } @@ -389,6 +429,7 @@ impl Res { pub fn article(&self) -> &'static str { match *self { Res::Def(kind, _) => kind.article(), + Res::NonMacroAttr(kind) => kind.article(), Res::Err => "an", _ => "a", } @@ -414,4 +455,14 @@ impl Res { _ => None, } } + + pub fn matches_ns(&self, ns: Namespace) -> bool { + match self { + Res::Def(kind, ..) => kind.matches_ns(ns), + Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => ns == Namespace::TypeNS, + Res::SelfCtor(..) | Res::Local(..) => ns == Namespace::ValueNS, + Res::NonMacroAttr(..) => ns == Namespace::MacroNS, + Res::Err => true, + } + } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 920635d838..a4557a0776 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -45,7 +45,7 @@ pub enum FnKind<'a> { ItemFn(Ident, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]), /// `fn foo(&self)` - Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]), + Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a [Attribute]), /// `|x, y| {}` Closure(&'a [Attribute]), @@ -481,13 +481,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_ty(typ); visitor.visit_nested_body(body); } - ItemKind::Fn(ref declaration, header, ref generics, body_id) => { + ItemKind::Fn(ref sig, ref generics, body_id) => { visitor.visit_fn(FnKind::ItemFn(item.ident, generics, - header, + sig.header, &item.vis, &item.attrs), - declaration, + &sig.decl, body_id, item.span, item.hir_id) @@ -1024,7 +1024,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(left_expression); visitor.visit_expr(right_expression) } - ExprKind::AddrOf(_, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { + ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { visitor.visit_expr(subexpression) } ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { @@ -1086,10 +1086,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprKind::Ret(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } - ExprKind::InlineAsm(_, ref outputs, ref inputs) => { - for expr in outputs.iter().chain(inputs.iter()) { - visitor.visit_expr(expr) - } + ExprKind::InlineAsm(ref asm) => { + walk_list!(visitor, visit_expr, &asm.outputs_exprs); + walk_list!(visitor, visit_expr, &asm.inputs_exprs); } ExprKind::Yield(ref subexpression, _) => { visitor.visit_expr(subexpression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e665e058e6..ec9d6802de 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -44,8 +44,7 @@ use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS}; use crate::hir::{GenericArg, ConstArg}; use crate::hir::ptr::P; use crate::lint; -use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, - ELIDED_LIFETIMES_IN_PATHS}; +use crate::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS}; use crate::middle::cstore::CrateStore; use crate::session::Session; use crate::session::config::nightly_options; @@ -65,9 +64,8 @@ use syntax::ast; use syntax::ptr::P as AstP; use syntax::ast::*; use syntax::errors; -use syntax::expand::SpecialDerives; use syntax::print::pprust; -use syntax::parse::token::{self, Nonterminal, Token}; +use syntax::token::{self, Nonterminal, Token}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::sess::ParseSess; use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned}; @@ -76,6 +74,8 @@ use syntax::visit::{self, Visitor}; use syntax_pos::hygiene::ExpnId; use syntax_pos::Span; +use rustc_error_codes::*; + const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; pub struct LoweringContext<'a> { @@ -184,9 +184,9 @@ pub trait Resolver { ns: Namespace, ) -> (ast::Path, Res); - fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; - fn lint_buffer(&mut self) -> &mut lint::LintBuffer; + + fn next_node_id(&mut self) -> NodeId; } type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream; @@ -301,7 +301,6 @@ enum ParamMode { enum ParenthesizedGenericArgs { Ok, - Warn, Err, } @@ -455,7 +454,6 @@ impl<'a> LoweringContext<'a> { | ItemKind::Union(_, ref generics) | ItemKind::Enum(_, ref generics) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(_, ref generics) | ItemKind::Trait(_, _, ref generics, ..) => { let def_id = self.lctx.resolver.definitions().local_def_id(item.id); let count = generics @@ -677,7 +675,8 @@ impl<'a> LoweringContext<'a> { } fn next_id(&mut self) -> hir::HirId { - self.lower_node_id(self.sess.next_node_id()) + let node_id = self.resolver.next_node_id(); + self.lower_node_id(node_id) } fn lower_res(&mut self, res: Res) -> Res { @@ -786,7 +785,7 @@ impl<'a> LoweringContext<'a> { hir_name: ParamName, parent_index: DefIndex, ) -> hir::GenericParam { - let node_id = self.sess.next_node_id(); + let node_id = self.resolver.next_node_id(); // Get the name we'll use to make the def-path. Note // that collisions are ok here and this shouldn't @@ -1000,18 +999,34 @@ impl<'a> LoweringContext<'a> { // Note that we explicitly do not walk the path. Since we don't really // lower attributes (we use the AST version) there is nowhere to keep // the `HirId`s. We don't actually need HIR version of attributes anyway. + let kind = match attr.kind { + AttrKind::Normal(ref item) => { + AttrKind::Normal(AttrItem { + path: item.path.clone(), + args: self.lower_mac_args(&item.args), + }) + } + AttrKind::DocComment(comment) => AttrKind::DocComment(comment) + }; + Attribute { - item: AttrItem { - path: attr.path.clone(), - tokens: self.lower_token_stream(attr.tokens.clone()), - }, + kind, id: attr.id, style: attr.style, - is_sugared_doc: attr.is_sugared_doc, span: attr.span, } } + fn lower_mac_args(&mut self, args: &MacArgs) -> MacArgs { + match *args { + MacArgs::Empty => MacArgs::Empty, + MacArgs::Delimited(dspan, delim, ref tokens) => + MacArgs::Delimited(dspan, delim, self.lower_token_stream(tokens.clone())), + MacArgs::Eq(eq_span, ref tokens) => + MacArgs::Eq(eq_span, self.lower_token_stream(tokens.clone())), + } + } + fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream { tokens .into_trees() @@ -1105,7 +1120,7 @@ impl<'a> LoweringContext<'a> { // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by // constructing the HIR for `impl bounds...` and then lowering that. - let impl_trait_node_id = self.sess.next_node_id(); + let impl_trait_node_id = self.resolver.next_node_id(); let parent_def_index = self.current_hir_id_owner.last().unwrap().0; self.resolver.definitions().create_def_with_parent( parent_def_index, @@ -1116,9 +1131,10 @@ impl<'a> LoweringContext<'a> { ); self.with_dyn_type_scope(false, |this| { + let node_id = this.resolver.next_node_id(); let ty = this.lower_ty( &Ty { - id: this.sess.next_node_id(), + id: node_id, kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), span: constraint.span, }, @@ -1149,13 +1165,64 @@ impl<'a> LoweringContext<'a> { } } - fn lower_generic_arg(&mut self, - arg: &ast::GenericArg, - itctx: ImplTraitContext<'_>) - -> hir::GenericArg { + fn lower_generic_arg( + &mut self, + arg: &ast::GenericArg, + itctx: ImplTraitContext<'_> + ) -> hir::GenericArg { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), - ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)), + ast::GenericArg::Type(ty) => { + // We parse const arguments as path types as we cannot distiguish them durring + // parsing. We try to resolve that ambiguity by attempting resolution in both the + // type and value namespaces. If we resolved the path in the value namespace, we + // transform it into a generic const argument. + if let TyKind::Path(ref qself, ref path) = ty.kind { + if let Some(partial_res) = self.resolver.get_partial_res(ty.id) { + let res = partial_res.base_res(); + if !res.matches_ns(Namespace::TypeNS) { + debug!( + "lower_generic_arg: Lowering type argument as const argument: {:?}", + ty, + ); + + // Construct a AnonConst where the expr is the "ty"'s path. + + let parent_def_index = + self.current_hir_id_owner.last().unwrap().0; + let node_id = self.resolver.next_node_id(); + + // Add a definition for the in-band const def. + self.resolver.definitions().create_def_with_parent( + parent_def_index, + node_id, + DefPathData::AnonConst, + ExpnId::root(), + ty.span, + ); + + let path_expr = Expr { + id: ty.id, + kind: ExprKind::Path(qself.clone(), path.clone()), + span: ty.span, + attrs: ThinVec::new(), + }; + + let ct = self.with_new_scopes(|this| { + hir::AnonConst { + hir_id: this.lower_node_id(node_id), + body: this.lower_const_body(&path_expr), + } + }); + return GenericArg::Const(ConstArg { + value: ct, + span: ty.span, + }); + } + } + } + GenericArg::Type(self.lower_ty_direct(&ty, itctx)) + } ast::GenericArg::Const(ct) => { GenericArg::Const(ConstArg { value: self.lower_anon_const(&ct), @@ -1212,8 +1279,8 @@ impl<'a> LoweringContext<'a> { &NodeMap::default(), ImplTraitContext::disallowed(), ), - unsafety: this.lower_unsafety(f.unsafety), - abi: f.abi, + unsafety: f.unsafety, + abi: this.lower_extern(f.ext), decl: this.lower_fn_decl(&f.decl, None, false, None), param_names: this.lower_fn_params_to_names(&f.decl), })) @@ -1585,7 +1652,7 @@ impl<'a> LoweringContext<'a> { name, })); - let def_node_id = self.context.sess.next_node_id(); + let def_node_id = self.context.resolver.next_node_id(); let hir_id = self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id); self.context.resolver.definitions().create_def_with_parent( @@ -1698,29 +1765,19 @@ impl<'a> LoweringContext<'a> { }; let parenthesized_generic_args = match partial_res.base_res() { // `a::b::Trait(Args)` - Res::Def(DefKind::Trait, _) - if i + 1 == proj_start => ParenthesizedGenericArgs::Ok, + Res::Def(DefKind::Trait, _) if i + 1 == proj_start => { + ParenthesizedGenericArgs::Ok + } // `a::b::Trait(Args)::TraitItem` - Res::Def(DefKind::Method, _) - | Res::Def(DefKind::AssocConst, _) - | Res::Def(DefKind::AssocTy, _) - if i + 2 == proj_start => - { + Res::Def(DefKind::Method, _) | + Res::Def(DefKind::AssocConst, _) | + Res::Def(DefKind::AssocTy, _) if i + 2 == proj_start => { ParenthesizedGenericArgs::Ok } // Avoid duplicated errors. Res::Err => ParenthesizedGenericArgs::Ok, // An error - Res::Def(DefKind::Struct, _) - | Res::Def(DefKind::Enum, _) - | Res::Def(DefKind::Union, _) - | Res::Def(DefKind::TyAlias, _) - | Res::Def(DefKind::Variant, _) if i + 1 == proj_start => - { - ParenthesizedGenericArgs::Err - } - // A warning for now, for compatibility reasons. - _ => ParenthesizedGenericArgs::Warn, + _ => ParenthesizedGenericArgs::Err, }; let num_lifetimes = type_def_id.map_or(0, |def_id| { @@ -1783,7 +1840,7 @@ impl<'a> LoweringContext<'a> { segment, param_mode, 0, - ParenthesizedGenericArgs::Warn, + ParenthesizedGenericArgs::Err, itctx.reborrow(), None, )); @@ -1859,15 +1916,6 @@ impl<'a> LoweringContext<'a> { } GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), - ParenthesizedGenericArgs::Warn => { - self.resolver.lint_buffer().buffer_lint( - PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, - CRATE_NODE_ID, - data.span, - msg.into(), - ); - (hir::GenericArgs::none(), true) - } ParenthesizedGenericArgs::Err => { let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg); err.span_label(data.span, "only `Fn` traits may use parentheses"); @@ -2096,13 +2144,6 @@ impl<'a> LoweringContext<'a> { }, ids) } - fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability { - match m { - Mutability::Mutable => hir::MutMutable, - Mutability::Immutable => hir::MutImmutable, - } - } - fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> hir::HirVec { // Skip the `...` (`CVarArgs`) trailing arguments from the AST, // as they are not explicit in HIR/Ty function signatures. @@ -2139,6 +2180,16 @@ impl<'a> LoweringContext<'a> { impl_trait_return_allow: bool, make_ret_async: Option, ) -> P { + debug!("lower_fn_decl(\ + fn_decl: {:?}, \ + in_band_ty_params: {:?}, \ + impl_trait_return_allow: {}, \ + make_ret_async: {:?})", + decl, + in_band_ty_params, + impl_trait_return_allow, + make_ret_async, + ); let lt_mode = if make_ret_async.is_some() { // In `async fn`, argument-position elided lifetimes // must be transformed into fresh generic parameters so that @@ -2431,7 +2482,7 @@ impl<'a> LoweringContext<'a> { hir::FunctionRetTy::Return(P(hir::Ty { kind: opaque_ty_ref, - span, + span: opaque_ty_span, hir_id: self.next_id(), })) } @@ -2541,7 +2592,7 @@ impl<'a> LoweringContext<'a> { hir::Lifetime { hir_id: self.lower_node_id(id), span, - name: name, + name, } } @@ -2672,7 +2723,7 @@ impl<'a> LoweringContext<'a> { fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), - mutbl: self.lower_mutability(mt.mutbl), + mutbl: mt.mutbl, } } @@ -2773,7 +2824,7 @@ impl<'a> LoweringContext<'a> { } PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)), PatKind::Ref(ref inner, mutbl) => { - hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl)) + hir::PatKind::Ref(self.lower_pat(inner), mutbl) } PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range( P(self.lower_expr(e1)), @@ -2801,19 +2852,23 @@ impl<'a> LoweringContext<'a> { let mut rest = None; let mut iter = pats.iter().enumerate(); - while let Some((idx, pat)) = iter.next() { - // Interpret the first `..` pattern as a subtuple pattern. + for (idx, pat) in iter.by_ref() { + // Interpret the first `..` pattern as a sub-tuple pattern. + // Note that unlike for slice patterns, + // where `xs @ ..` is a legal sub-slice pattern, + // it is not a legal sub-tuple pattern. if pat.is_rest() { rest = Some((idx, pat.span)); break; } - // It was not a subslice pattern so lower it normally. + // It was not a sub-tuple pattern so lower it normally. elems.push(self.lower_pat(pat)); } - while let Some((_, pat)) = iter.next() { - // There was a previous subtuple pattern; make sure we don't allow more. + for (_, pat) in iter { + // There was a previous sub-tuple pattern; make sure we don't allow more... if pat.is_rest() { + // ...but there was one again, so error. self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx); } else { elems.push(self.lower_pat(pat)); @@ -2823,6 +2878,12 @@ impl<'a> LoweringContext<'a> { (elems.into(), rest.map(|(ddpos, _)| ddpos)) } + /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into + /// `hir::PatKind::Slice(before, slice, after)`. + /// + /// When encountering `($binding_mode $ident @)? ..` (`slice`), + /// this is interpreted as a sub-slice pattern semantically. + /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`. fn lower_pat_slice(&mut self, pats: &[AstP]) -> hir::PatKind { let mut before = Vec::new(); let mut after = Vec::new(); @@ -2830,14 +2891,17 @@ impl<'a> LoweringContext<'a> { let mut prev_rest_span = None; let mut iter = pats.iter(); - while let Some(pat) = iter.next() { - // Interpret the first `((ref mut?)? x @)? ..` pattern as a subslice pattern. + // Lower all the patterns until the first occurence of a sub-slice pattern. + for pat in iter.by_ref() { match pat.kind { + // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here. PatKind::Rest => { prev_rest_span = Some(pat.span); slice = Some(self.pat_wild_with_node_id_of(pat)); break; }, + // Found a sub-slice pattern `$binding_mode $ident @ ..`. + // Record, lower it to `$binding_mode $ident @ _`, and stop here. PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { prev_rest_span = Some(sub.span); let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); @@ -2845,14 +2909,13 @@ impl<'a> LoweringContext<'a> { slice = Some(self.pat_with_node_id_of(pat, node)); break; }, - _ => {} + // It was not a subslice pattern so lower it normally. + _ => before.push(self.lower_pat(pat)), } - - // It was not a subslice pattern so lower it normally. - before.push(self.lower_pat(pat)); } - while let Some(pat) = iter.next() { + // Lower all the patterns after the first sub-slice pattern. + for pat in iter { // There was a previous subslice pattern; make sure we don't allow more. let rest_span = match pat.kind { PatKind::Rest => Some(pat.span), @@ -2864,8 +2927,10 @@ impl<'a> LoweringContext<'a> { _ => None, }; if let Some(rest_span) = rest_span { + // We have e.g., `[a, .., b, ..]`. That's no good, error! self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice"); } else { + // Lower the pattern normally. after.push(self.lower_pat(pat)); } } @@ -3253,7 +3318,7 @@ impl<'a> LoweringContext<'a> { Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"), None => ( - self.sess.next_node_id(), + self.resolver.next_node_id(), "`&` without an explicit lifetime name cannot be used here", "explicit lifetime name needed here", ), @@ -3290,7 +3355,7 @@ impl<'a> LoweringContext<'a> { span, "expected 'implicit elided lifetime not allowed' error", ); - let id = self.sess.next_node_id(); + let id = self.resolver.next_node_id(); self.new_named_lifetime(id, span, hir::LifetimeName::Error) } // `PassThrough` is the normal case. @@ -3386,7 +3451,7 @@ pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool { // either in std or core, i.e. has either a `::std::ops::Range` or // `::core::ops::Range` prefix. fn is_range_path(path: &Path) -> bool { - let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.as_str().to_string()).collect(); + let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.to_string()).collect(); let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect(); // "{{root}}" is the equivalent of `::` prefix in `Path`. @@ -3427,7 +3492,7 @@ pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool { ExprKind::Call(ref func, _) => { if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.kind { if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.kind { - let new_call = segment.ident.as_str() == "new"; + let new_call = segment.ident.name == sym::new; return is_range_path(&path) && is_lit(sess, &expr.span) && new_call; } } diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 73db762a64..f8465baeb1 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -11,6 +11,8 @@ use syntax::ast::*; use syntax::source_map::{respan, DesugaringKind, Span, Spanned}; use syntax::symbol::{sym, Symbol}; +use rustc_error_codes::*; + impl LoweringContext<'_> { fn lower_exprs(&mut self, exprs: &[AstP]) -> HirVec { exprs.iter().map(|x| self.lower_expr(x)).collect() @@ -63,10 +65,9 @@ impl LoweringContext<'_> { let expr = P(self.lower_expr(expr)); hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) } - ExprKind::AddrOf(m, ref ohs) => { - let m = self.lower_mutability(m); + ExprKind::AddrOf(k, m, ref ohs) => { let ohs = P(self.lower_expr(ohs)); - hir::ExprKind::AddrOf(m, ohs) + hir::ExprKind::AddrOf(k, m, ohs) } ExprKind::Let(ref pat, ref scrutinee) => self.lower_expr_let(e.span, pat, scrutinee), ExprKind::If(ref cond, ref then, ref else_opt) => { @@ -474,7 +475,6 @@ impl LoweringContext<'_> { async_gen_kind: hir::AsyncGeneratorKind, body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::ExprKind { - let capture_clause = self.lower_capture_clause(capture_clause); let output = match ret_ty { Some(ty) => FunctionRetTy::Ty(ty), None => FunctionRetTy::Default(span), @@ -495,7 +495,7 @@ impl LoweringContext<'_> { decl, body_id, span, - Some(hir::GeneratorMovability::Static) + Some(hir::Movability::Static) ); let generator = hir::Expr { hir_id: self.lower_node_id(closure_node_id), @@ -595,7 +595,7 @@ impl LoweringContext<'_> { }; // `::std::task::Poll::Ready(result) => break result` - let loop_node_id = self.sess.next_node_id(); + let loop_node_id = self.resolver.next_node_id(); let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { let x_ident = Ident::with_dummy_span(sym::result); @@ -701,7 +701,6 @@ impl LoweringContext<'_> { generator_kind, movability, ); - let capture_clause = this.lower_capture_clause(capture_clause); this.current_item = prev; hir::ExprKind::Closure( capture_clause, @@ -713,20 +712,13 @@ impl LoweringContext<'_> { }) } - fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause { - match c { - CaptureBy::Value => hir::CaptureByValue, - CaptureBy::Ref => hir::CaptureByRef, - } - } - fn generator_movability_for_fn( &mut self, decl: &FnDecl, fn_decl_span: Span, generator_kind: Option, movability: Movability, - ) -> Option { + ) -> Option { match generator_kind { Some(hir::GeneratorKind::Gen) => { if !decl.inputs.is_empty() { @@ -737,10 +729,7 @@ impl LoweringContext<'_> { "generators cannot have explicit parameters" ); } - Some(match movability { - Movability::Movable => hir::GeneratorMovability::Movable, - Movability::Static => hir::GeneratorMovability::Static, - }) + Some(movability) }, Some(hir::GeneratorKind::Async(_)) => { bug!("non-`async` closure body turned `async` during lowering"); @@ -811,7 +800,7 @@ impl LoweringContext<'_> { this.expr(fn_decl_span, async_body, ThinVec::new()) }); hir::ExprKind::Closure( - this.lower_capture_clause(capture_clause), + capture_clause, fn_decl, body_id, fn_decl_span, @@ -977,7 +966,7 @@ impl LoweringContext<'_> { } fn lower_expr_asm(&mut self, asm: &InlineAsm) -> hir::ExprKind { - let hir_asm = hir::InlineAsm { + let inner = hir::InlineAsmInner { inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(), outputs: asm.outputs .iter() @@ -995,18 +984,18 @@ impl LoweringContext<'_> { alignstack: asm.alignstack, dialect: asm.dialect, }; - - let outputs = asm.outputs - .iter() - .map(|out| self.lower_expr(&out.expr)) - .collect(); - - let inputs = asm.inputs - .iter() - .map(|&(_, ref input)| self.lower_expr(input)) - .collect(); - - hir::ExprKind::InlineAsm(P(hir_asm), outputs, inputs) + let hir_asm = hir::InlineAsm { + inner, + inputs_exprs: asm.inputs + .iter() + .map(|&(_, ref input)| self.lower_expr(input)) + .collect(), + outputs_exprs: asm.outputs + .iter() + .map(|out| self.lower_expr(&out.expr)) + .collect(), + }; + hir::ExprKind::InlineAsm(P(hir_asm)) } fn lower_field(&mut self, f: &Field) -> hir::Field { @@ -1350,7 +1339,11 @@ impl LoweringContext<'_> { } fn expr_mut_addr_of(&mut self, span: Span, e: P) -> hir::Expr { - self.expr(span, hir::ExprKind::AddrOf(hir::MutMutable, e), ThinVec::new()) + self.expr( + span, + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mutable, e), + ThinVec::new(), + ) } fn expr_unit(&mut self, sp: Span) -> hir::Expr { diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 9da87090c7..ff9d8c85df 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -12,17 +12,19 @@ use crate::hir::def::{Res, DefKind}; use crate::util::nodemap::NodeMap; use rustc_data_structures::thin_vec::ThinVec; +use rustc_target::spec::abi; use std::collections::BTreeSet; use smallvec::SmallVec; use syntax::attr; use syntax::ast::*; use syntax::visit::{self, Visitor}; -use syntax::expand::SpecialDerives; -use syntax::source_map::{respan, DesugaringKind, Spanned}; +use syntax::source_map::{respan, DesugaringKind}; use syntax::symbol::{kw, sym}; use syntax_pos::Span; +use rustc_error_codes::*; + pub(super) struct ItemLowerer<'tcx, 'interner> { pub(super) lctx: &'tcx mut LoweringContext<'interner>, } @@ -227,17 +229,11 @@ impl LoweringContext<'_> { pub fn lower_item(&mut self, i: &Item) -> Option { let mut ident = i.ident; let mut vis = self.lower_visibility(&i.vis, None); - let mut attrs = self.lower_attrs_extendable(&i.attrs); - if self.resolver.has_derives(i.id, SpecialDerives::PARTIAL_EQ | SpecialDerives::EQ) { - // Add `#[structural_match]` if the item derived both `PartialEq` and `Eq`. - let ident = Ident::new(sym::structural_match, i.span); - attrs.push(attr::mk_attr_outer(attr::mk_word_item(ident))); - } - let attrs = attrs.into(); + let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.kind { if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) { - let body = self.lower_token_stream(def.stream()); + let body = self.lower_token_stream(def.body.inner_tokens()); let hir_id = self.lower_node_id(i.id); self.exported_macros.push(hir::MacroDef { name: ident.name, @@ -295,7 +291,7 @@ impl LoweringContext<'_> { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) } ), - self.lower_mutability(m), + m, self.lower_const_body(e), ) } @@ -312,7 +308,7 @@ impl LoweringContext<'_> { self.lower_const_body(e) ) } - ItemKind::Fn(ref decl, header, ref generics, ref body) => { + ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => { let fn_def_id = self.resolver.definitions().local_def_id(id); self.with_new_scopes(|this| { this.current_item = Some(ident.span); @@ -323,7 +319,7 @@ impl LoweringContext<'_> { // declaration (decl), not the return types. let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body); - let (generics, fn_decl) = this.add_in_band_defs( + let (generics, decl) = this.add_in_band_defs( generics, fn_def_id, AnonymousLifetimeMode::PassThrough, @@ -334,32 +330,29 @@ impl LoweringContext<'_> { header.asyncness.node.opt_return_id() ), ); - - hir::ItemKind::Fn( - fn_decl, - this.lower_fn_header(header), - generics, - body_id, - ) + let sig = hir::FnSig { decl, header: this.lower_fn_header(header) }; + hir::ItemKind::Fn(sig, generics, body_id) }) } ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)), ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)), ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)), - ItemKind::TyAlias(ref t, ref generics) => hir::ItemKind::TyAlias( - self.lower_ty(t, ImplTraitContext::disallowed()), - self.lower_generics(generics, ImplTraitContext::disallowed()), - ), - ItemKind::OpaqueTy(ref b, ref generics) => hir::ItemKind::OpaqueTy( - hir::OpaqueTy { - generics: self.lower_generics(generics, - ImplTraitContext::OpaqueTy(None)), - bounds: self.lower_param_bounds(b, - ImplTraitContext::OpaqueTy(None)), - impl_trait_fn: None, - origin: hir::OpaqueTyOrigin::TypeAlias, + ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() { + None => { + let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); + let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); + hir::ItemKind::TyAlias(ty, generics) }, - ), + Some(bounds) => { + let ty = hir::OpaqueTy { + generics: self.lower_generics(generics, ImplTraitContext::OpaqueTy(None)), + bounds: self.lower_param_bounds(bounds, ImplTraitContext::OpaqueTy(None)), + impl_trait_fn: None, + origin: hir::OpaqueTyOrigin::TypeAlias, + }; + hir::ItemKind::OpaqueTy(ty) + } + } ItemKind::Enum(ref enum_definition, ref generics) => { hir::ItemKind::Enum( hir::EnumDef { @@ -444,8 +437,8 @@ impl LoweringContext<'_> { ); hir::ItemKind::Impl( - self.lower_unsafety(unsafety), - self.lower_impl_polarity(polarity), + unsafety, + polarity, self.lower_defaultness(defaultness, true /* [1] */), generics, trait_ref, @@ -460,8 +453,8 @@ impl LoweringContext<'_> { .map(|item| self.lower_trait_item_ref(item)) .collect(); hir::ItemKind::Trait( - self.lower_is_auto(is_auto), - self.lower_unsafety(unsafety), + is_auto, + unsafety, self.lower_generics(generics, ImplTraitContext::disallowed()), bounds, items, @@ -533,7 +526,7 @@ impl LoweringContext<'_> { let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { - seg.id = self.sess.next_node_id(); + seg.id = self.resolver.next_node_id(); } let span = path.span; @@ -610,7 +603,7 @@ impl LoweringContext<'_> { // Give the segments new node-ids since they are being cloned. for seg in &mut prefix.segments { - seg.id = self.sess.next_node_id(); + seg.id = self.resolver.next_node_id(); } // Each `use` import is an item and thus are owners of the @@ -730,7 +723,7 @@ impl LoweringContext<'_> { } ForeignItemKind::Static(ref t, m) => { hir::ForeignItemKind::Static( - self.lower_ty(t, ImplTraitContext::disallowed()), self.lower_mutability(m)) + self.lower_ty(t, ImplTraitContext::disallowed()), m) } ForeignItemKind::Ty => hir::ForeignItemKind::Type, ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), @@ -742,7 +735,7 @@ impl LoweringContext<'_> { fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod { hir::ForeignMod { - abi: fm.abi, + abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)), items: fm.items .iter() .map(|x| self.lower_foreign_item(x)) @@ -925,16 +918,20 @@ impl LoweringContext<'_> { (generics, hir::ImplItemKind::Method(sig, body_id)) } - ImplItemKind::TyAlias(ref ty) => ( - self.lower_generics(&i.generics, ImplTraitContext::disallowed()), - hir::ImplItemKind::TyAlias(self.lower_ty(ty, ImplTraitContext::disallowed())), - ), - ImplItemKind::OpaqueTy(ref bounds) => ( - self.lower_generics(&i.generics, ImplTraitContext::disallowed()), - hir::ImplItemKind::OpaqueTy( - self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), - ), - ), + ImplItemKind::TyAlias(ref ty) => { + let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); + let kind = match ty.kind.opaque_top_hack() { + None => { + let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); + hir::ImplItemKind::TyAlias(ty) + } + Some(bs) => { + let bounds = self.lower_param_bounds(bs, ImplTraitContext::disallowed()); + hir::ImplItemKind::OpaqueTy(bounds) + } + }; + (generics, kind) + }, ImplItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"), }; @@ -959,11 +956,13 @@ impl LoweringContext<'_> { span: i.span, vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), - kind: match i.kind { + kind: match &i.kind { ImplItemKind::Const(..) => hir::AssocItemKind::Const, - ImplItemKind::TyAlias(..) => hir::AssocItemKind::Type, - ImplItemKind::OpaqueTy(..) => hir::AssocItemKind::OpaqueTy, - ImplItemKind::Method(ref sig, _) => hir::AssocItemKind::Method { + ImplItemKind::TyAlias(ty) => match ty.kind.opaque_top_hack() { + None => hir::AssocItemKind::Type, + Some(_) => hir::AssocItemKind::OpaqueTy, + }, + ImplItemKind::Method(sig, _) => hir::AssocItemKind::Method { has_self: sig.decl.has_self(), }, ImplItemKind::Macro(..) => unimplemented!(), @@ -1022,13 +1021,6 @@ impl LoweringContext<'_> { } } - fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity { - match i { - ImplPolarity::Positive => hir::ImplPolarity::Positive, - ImplPolarity::Negative => hir::ImplPolarity::Negative, - } - } - fn record_body(&mut self, params: HirVec, value: hir::Expr) -> hir::BodyId { let body = hir::Body { generator_kind: self.generator_kind, @@ -1266,11 +1258,11 @@ impl LoweringContext<'_> { fn lower_method_sig( &mut self, generics: &Generics, - sig: &MethodSig, + sig: &FnSig, fn_def_id: DefId, impl_trait_return_allow: bool, is_async: Option, - ) -> (hir::Generics, hir::MethodSig) { + ) -> (hir::Generics, hir::FnSig) { let header = self.lower_fn_header(sig.header); let (generics, decl) = self.add_in_band_defs( generics, @@ -1283,39 +1275,46 @@ impl LoweringContext<'_> { is_async, ), ); - (generics, hir::MethodSig { header, decl }) - } - - fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto { - match a { - IsAuto::Yes => hir::IsAuto::Yes, - IsAuto::No => hir::IsAuto::No, - } + (generics, hir::FnSig { header, decl }) } fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { hir::FnHeader { - unsafety: self.lower_unsafety(h.unsafety), + unsafety: h.unsafety, asyncness: self.lower_asyncness(h.asyncness.node), - constness: self.lower_constness(h.constness), - abi: h.abi, + constness: h.constness.node, + abi: self.lower_extern(h.ext), } } - pub(super) fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety { - match u { - Unsafety::Unsafe => hir::Unsafety::Unsafe, - Unsafety::Normal => hir::Unsafety::Normal, - } + pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi { + abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| { + self.error_on_invalid_abi(abi); + abi::Abi::Rust + }) } - fn lower_constness(&mut self, c: Spanned) -> hir::Constness { - match c.node { - Constness::Const => hir::Constness::Const, - Constness::NotConst => hir::Constness::NotConst, + pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi { + match ext { + Extern::None => abi::Abi::Rust, + Extern::Implicit => abi::Abi::C, + Extern::Explicit(abi) => self.lower_abi(abi), } } + fn error_on_invalid_abi(&self, abi: StrLit) { + struct_span_err!( + self.sess, + abi.span, + E0703, + "invalid ABI: found `{}`", + abi.symbol + ) + .span_label(abi.span, "invalid ABI") + .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) + .emit(); + } + fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync { match a { IsAsync::Async { .. } => hir::IsAsync::Async, diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index f670d5abe8..ff793fd861 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -12,9 +12,9 @@ //! for the `Code` associated with a particular NodeId. use crate::hir as ast; +use crate::hir::intravisit::FnKind; use crate::hir::map; use crate::hir::{Expr, FnDecl, Node}; -use crate::hir::intravisit::FnKind; use syntax::ast::{Attribute, Ident}; use syntax_pos::Span; @@ -29,11 +29,15 @@ use syntax_pos::Span; /// /// To construct one, use the `Code::from_node` function. #[derive(Copy, Clone, Debug)] -pub struct FnLikeNode<'a> { node: Node<'a> } +pub struct FnLikeNode<'a> { + node: Node<'a>, +} /// MaybeFnLike wraps a method that indicates if an object /// corresponds to some FnLikeNode. -trait MaybeFnLike { fn is_fn_like(&self) -> bool; } +trait MaybeFnLike { + fn is_fn_like(&self) -> bool; +} impl MaybeFnLike for ast::Item { fn is_fn_like(&self) -> bool { @@ -96,7 +100,7 @@ impl<'a> Code<'a> { Code::from_node(map, map.get_parent_node(id)) } map::Node::Expr(expr) => Some(Code::Expr(expr)), - node => FnLikeNode::from_node(node).map(Code::FnLike) + node => FnLikeNode::from_node(node).map(Code::FnLike), } } } @@ -104,15 +108,15 @@ impl<'a> Code<'a> { /// These are all the components one can extract from a fn item for /// use when implementing FnLikeNode operations. struct ItemFnParts<'a> { - ident: Ident, - decl: &'a ast::FnDecl, - header: ast::FnHeader, - vis: &'a ast::Visibility, + ident: Ident, + decl: &'a ast::FnDecl, + header: ast::FnHeader, + vis: &'a ast::Visibility, generics: &'a ast::Generics, - body: ast::BodyId, - id: ast::HirId, - span: Span, - attrs: &'a [Attribute], + body: ast::BodyId, + id: ast::HirId, + span: Span, + attrs: &'a [Attribute], } /// These are all the components one can extract from a closure expr @@ -127,13 +131,7 @@ struct ClosureParts<'a> { impl<'a> ClosureParts<'a> { fn new(d: &'a FnDecl, b: ast::BodyId, id: ast::HirId, s: Span, attrs: &'a [Attribute]) -> Self { - ClosureParts { - decl: d, - body: b, - id, - span: s, - attrs, - } + ClosureParts { decl: d, body: b, id, span: s, attrs } } } @@ -145,39 +143,41 @@ impl<'a> FnLikeNode<'a> { map::Node::TraitItem(tm) => tm.is_fn_like(), map::Node::ImplItem(it) => it.is_fn_like(), map::Node::Expr(e) => e.is_fn_like(), - _ => false + _ => false, }; - if fn_like { - Some(FnLikeNode { - node, - }) - } else { - None - } + fn_like.then_some(FnLikeNode { node }) } pub fn body(self) -> ast::BodyId { - self.handle(|i: ItemFnParts<'a>| i.body, - |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body, - |c: ClosureParts<'a>| c.body) + self.handle( + |i: ItemFnParts<'a>| i.body, + |_, _, _: &'a ast::FnSig, _, body: ast::BodyId, _, _| body, + |c: ClosureParts<'a>| c.body, + ) } pub fn decl(self) -> &'a FnDecl { - self.handle(|i: ItemFnParts<'a>| &*i.decl, - |_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl, - |c: ClosureParts<'a>| c.decl) + self.handle( + |i: ItemFnParts<'a>| &*i.decl, + |_, _, sig: &'a ast::FnSig, _, _, _, _| &sig.decl, + |c: ClosureParts<'a>| c.decl, + ) } pub fn span(self) -> Span { - self.handle(|i: ItemFnParts<'_>| i.span, - |_, _, _: &'a ast::MethodSig, _, _, span, _| span, - |c: ClosureParts<'_>| c.span) + self.handle( + |i: ItemFnParts<'_>| i.span, + |_, _, _: &'a ast::FnSig, _, _, span, _| span, + |c: ClosureParts<'_>| c.span, + ) } pub fn id(self) -> ast::HirId { - self.handle(|i: ItemFnParts<'_>| i.id, - |id, _, _: &'a ast::MethodSig, _, _, _, _| id, - |c: ClosureParts<'_>| c.id) + self.handle( + |i: ItemFnParts<'_>| i.id, + |id, _, _: &'a ast::FnSig, _, _, _, _| id, + |c: ClosureParts<'_>| c.id, + ) } pub fn constness(self) -> ast::Constness { @@ -196,41 +196,40 @@ impl<'a> FnLikeNode<'a> { let item = |p: ItemFnParts<'a>| -> FnKind<'a> { FnKind::ItemFn(p.ident, p.generics, p.header, p.vis, p.attrs) }; - let closure = |c: ClosureParts<'a>| { - FnKind::Closure(c.attrs) - }; - let method = |_, ident: Ident, sig: &'a ast::MethodSig, vis, _, _, attrs| { + let closure = |c: ClosureParts<'a>| FnKind::Closure(c.attrs); + let method = |_, ident: Ident, sig: &'a ast::FnSig, vis, _, _, attrs| { FnKind::Method(ident, sig, vis, attrs) }; self.handle(item, method, closure) } - fn handle(self, item_fn: I, method: M, closure: C) -> A where + fn handle(self, item_fn: I, method: M, closure: C) -> A + where I: FnOnce(ItemFnParts<'a>) -> A, - M: FnOnce(ast::HirId, - Ident, - &'a ast::MethodSig, - Option<&'a ast::Visibility>, - ast::BodyId, - Span, - &'a [Attribute]) - -> A, + M: FnOnce( + ast::HirId, + Ident, + &'a ast::FnSig, + Option<&'a ast::Visibility>, + ast::BodyId, + Span, + &'a [Attribute], + ) -> A, C: FnOnce(ClosureParts<'a>) -> A, { match self.node { map::Node::Item(i) => match i.kind { - ast::ItemKind::Fn(ref decl, header, ref generics, block) => - item_fn(ItemFnParts { - id: i.hir_id, - ident: i.ident, - decl: &decl, - body: block, - vis: &i.vis, - span: i.span, - attrs: &i.attrs, - header, - generics, - }), + ast::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts { + id: i.hir_id, + ident: i.ident, + decl: &sig.decl, + body: block, + vis: &i.vis, + span: i.span, + attrs: &i.attrs, + header: sig.header, + generics, + }), _ => bug!("item FnLikeNode that is not fn-like"), }, map::Node::TraitItem(ti) => match ti.kind { @@ -239,17 +238,16 @@ impl<'a> FnLikeNode<'a> { } _ => bug!("trait method FnLikeNode that is not fn-like"), }, - map::Node::ImplItem(ii) => { - match ii.kind { - ast::ImplItemKind::Method(ref sig, body) => { - method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) - } - _ => bug!("impl method FnLikeNode that is not fn-like") + map::Node::ImplItem(ii) => match ii.kind { + ast::ImplItemKind::Method(ref sig, body) => { + method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) } + _ => bug!("impl method FnLikeNode that is not fn-like"), }, map::Node::Expr(e) => match e.kind { - ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => - closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs)), + ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => { + closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs)) + } _ => bug!("expr FnLikeNode that is not fn-like"), }, _ => bug!("other FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index b0fa844c81..76aa186696 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,20 +1,20 @@ use super::*; use crate::dep_graph::{DepGraph, DepKind, DepNodeIndex}; use crate::hir; +use crate::hir::def_id::{CrateNum, LOCAL_CRATE}; +use crate::hir::intravisit::{NestedVisitorMap, Visitor}; use crate::hir::map::HirEntryMap; -use crate::hir::def_id::{LOCAL_CRATE, CrateNum}; -use crate::hir::intravisit::{Visitor, NestedVisitorMap}; -use rustc_data_structures::svh::Svh; -use rustc_index::vec::IndexVec; use crate::ich::Fingerprint; use crate::middle::cstore::CrateStore; use crate::session::CrateDisambiguator; use crate::session::Session; use crate::util::nodemap::FxHashMap; +use rustc_data_structures::svh::Svh; +use rustc_index::vec::IndexVec; +use std::iter::repeat; use syntax::ast::NodeId; use syntax::source_map::SourceMap; use syntax_pos::Span; -use std::iter::repeat; use crate::ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -82,11 +82,13 @@ fn alloc_hir_dep_nodes( where I: for<'a> HashStable>, { - let sig = dep_graph.input_task( - def_path_hash.to_dep_node(DepKind::Hir), - &mut *hcx, - HirItemLike { item_like: &item_like, hash_bodies: false }, - ).1; + let sig = dep_graph + .input_task( + def_path_hash.to_dep_node(DepKind::Hir), + &mut *hcx, + HirItemLike { item_like: &item_like, hash_bodies: false }, + ) + .1; let (full, hash) = input_dep_node_and_hash( dep_graph, hcx, @@ -98,13 +100,14 @@ where } impl<'a, 'hir> NodeCollector<'a, 'hir> { - pub(super) fn root(sess: &'a Session, - krate: &'hir Crate, - dep_graph: &'a DepGraph, - definitions: &'a definitions::Definitions, - hir_to_node_id: &'a FxHashMap, - mut hcx: StableHashingContext<'a>) - -> NodeCollector<'a, 'hir> { + pub(super) fn root( + sess: &'a Session, + krate: &'hir Crate, + dep_graph: &'a DepGraph, + definitions: &'a definitions::Definitions, + hir_to_node_id: &'a FxHashMap, + mut hcx: StableHashingContext<'a>, + ) -> NodeCollector<'a, 'hir> { let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); let mut hir_body_nodes = Vec::new(); @@ -161,36 +164,43 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { hcx, hir_body_nodes, }; - collector.insert_entry(hir::CRATE_HIR_ID, Entry { - parent: hir::CRATE_HIR_ID, - dep_node: root_mod_sig_dep_index, - node: Node::Crate, - }); + collector.insert_entry( + hir::CRATE_HIR_ID, + Entry { + parent: hir::CRATE_HIR_ID, + dep_node: root_mod_sig_dep_index, + node: Node::Crate, + }, + ); collector } - pub(super) fn finalize_and_compute_crate_hash(mut self, - crate_disambiguator: CrateDisambiguator, - cstore: &dyn CrateStore, - commandline_args_hash: u64) - -> (HirEntryMap<'hir>, Svh) - { + pub(super) fn finalize_and_compute_crate_hash( + mut self, + crate_disambiguator: CrateDisambiguator, + cstore: &dyn CrateStore, + commandline_args_hash: u64, + ) -> (HirEntryMap<'hir>, Svh) { self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); - let node_hashes = self - .hir_body_nodes - .iter() - .fold(Fingerprint::ZERO, |combined_fingerprint, &(def_path_hash, fingerprint)| { + let node_hashes = self.hir_body_nodes.iter().fold( + Fingerprint::ZERO, + |combined_fingerprint, &(def_path_hash, fingerprint)| { combined_fingerprint.combine(def_path_hash.0.combine(fingerprint)) - }); + }, + ); - let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { - let name = cstore.crate_name_untracked(cnum); - let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); - let hash = cstore.crate_hash_untracked(cnum); - (name, disambiguator, hash) - }).collect(); + let mut upstream_crates: Vec<_> = cstore + .crates_untracked() + .iter() + .map(|&cnum| { + let name = cstore.crate_name_untracked(cnum); + let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); + let hash = cstore.crate_hash_untracked(cnum); + (name, disambiguator, hash) + }) + .collect(); upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis)); @@ -211,7 +221,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let crate_hash_input = ( ((node_hashes, upstream_crates), source_file_names), - (commandline_args_hash, crate_disambiguator.to_fingerprint()) + (commandline_args_hash, crate_disambiguator.to_fingerprint()), ); let (_, crate_hash) = input_dep_node_and_hash( @@ -255,10 +265,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { if hir_id.owner != self.current_dep_node_owner { let node_str = match self.definitions.opt_def_index(node_id) { - Some(def_index) => { - self.definitions.def_path(def_index).to_string_no_crate() - } - None => format!("{:?}", node) + Some(def_index) => self.definitions.def_path(def_index).to_string_no_crate(), + None => format!("{:?}", node), }; let forgot_str = if hir_id == crate::hir::DUMMY_HIR_ID { @@ -273,9 +281,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", self.source_map.span_to_string(span), node_str, - self.definitions - .def_path(self.current_dep_node_owner) - .to_string_no_crate(), + self.definitions.def_path(self.current_dep_node_owner).to_string_no_crate(), self.current_dep_node_owner, self.definitions.def_path(hir_id.owner).to_string_no_crate(), hir_id.owner, @@ -287,22 +293,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { self.insert_entry(hir_id, entry); } - fn with_parent( - &mut self, - parent_node_id: HirId, - f: F, - ) { + fn with_parent(&mut self, parent_node_id: HirId, f: F) { let parent_node = self.parent_node; self.parent_node = parent_node_id; f(self); self.parent_node = parent_node; } - fn with_dep_node_owner HashStable>, - F: FnOnce(&mut Self)>(&mut self, - dep_node_owner: DefIndex, - item_like: &T, - f: F) { + fn with_dep_node_owner< + T: for<'b> HashStable>, + F: FnOnce(&mut Self), + >( + &mut self, + dep_node_owner: DefIndex, + item_like: &T, + f: F, + ) { let prev_owner = self.current_dep_node_owner; let prev_signature_dep_index = self.current_signature_dep_index; let prev_full_dep_index = self.current_full_dep_index; @@ -369,8 +375,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_item(&mut self, i: &'hir Item) { debug!("visit_item: {:?}", i); - debug_assert_eq!(i.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap()); + debug_assert_eq!( + i.hir_id.owner, + self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap() + ); self.with_dep_node_owner(i.hir_id.owner, i, |this| { this.insert(i.span, i.hir_id, Node::Item(i)); this.with_parent(i.hir_id, |this| { @@ -399,8 +407,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_trait_item(&mut self, ti: &'hir TraitItem) { - debug_assert_eq!(ti.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap()); + debug_assert_eq!( + ti.hir_id.owner, + self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap() + ); self.with_dep_node_owner(ti.hir_id.owner, ti, |this| { this.insert(ti.span, ti.hir_id, Node::TraitItem(ti)); @@ -411,8 +421,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_impl_item(&mut self, ii: &'hir ImplItem) { - debug_assert_eq!(ii.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap()); + debug_assert_eq!( + ii.hir_id.owner, + self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap() + ); self.with_dep_node_owner(ii.hir_id.owner, ii, |this| { this.insert(ii.span, ii.hir_id, Node::ImplItem(ii)); @@ -423,11 +435,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_pat(&mut self, pat: &'hir Pat) { - let node = if let PatKind::Binding(..) = pat.kind { - Node::Binding(pat) - } else { - Node::Pat(pat) - }; + let node = + if let PatKind::Binding(..) = pat.kind { Node::Binding(pat) } else { Node::Pat(pat) }; self.insert(pat.span, pat.hir_id, node); self.with_parent(pat.hir_id, |this| { @@ -492,8 +501,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_fn(&mut self, fk: intravisit::FnKind<'hir>, fd: &'hir FnDecl, - b: BodyId, s: Span, id: HirId) { + fn visit_fn( + &mut self, + fk: intravisit::FnKind<'hir>, + fd: &'hir FnDecl, + b: BodyId, + s: Span, + id: HirId, + ) { assert_eq!(self.parent_node, id); intravisit::walk_fn(self, fk, fd, b, s, id); } @@ -507,9 +522,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_local(&mut self, l: &'hir Local) { self.insert(l.span, l.hir_id, Node::Local(l)); - self.with_parent(l.hir_id, |this| { - intravisit::walk_local(this, l) - }) + self.with_parent(l.hir_id, |this| intravisit::walk_local(this, l)) } fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) { @@ -518,9 +531,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_vis(&mut self, visibility: &'hir Visibility) { match visibility.node { - VisibilityKind::Public | - VisibilityKind::Crate(_) | - VisibilityKind::Inherited => {} + VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {} VisibilityKind::Restricted { hir_id, .. } => { self.insert(visibility.span, hir_id, Node::Visibility(visibility)); self.with_parent(hir_id, |this| { @@ -560,13 +571,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) { // Do not visit the duplicate information in TraitItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let TraitItemRef { - id, - ident: _, - kind: _, - span: _, - defaultness: _, - } = *ii; + let TraitItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii; self.visit_nested_trait_item(id); } @@ -574,14 +579,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) { // Do not visit the duplicate information in ImplItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let ImplItemRef { - id, - ident: _, - kind: _, - span: _, - vis: _, - defaultness: _, - } = *ii; + let ImplItemRef { id, ident: _, kind: _, span: _, vis: _, defaultness: _ } = *ii; self.visit_nested_impl_item(id); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 450ab94717..1ba0e993f0 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -5,21 +5,21 @@ //! expressions) that are mostly just leftovers. use crate::hir; -use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, CRATE_DEF_INDEX}; +use crate::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::ich::Fingerprint; use crate::session::CrateDisambiguator; use crate::util::nodemap::NodeMap; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::{IndexVec}; use rustc_data_structures::stable_hasher::StableHasher; +use rustc_index::vec::IndexVec; use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; use syntax::ast; -use syntax_pos::symbol::{Symbol, sym}; use syntax_pos::hygiene::ExpnId; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::symbol::{sym, Symbol}; +use syntax_pos::Span; /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` @@ -32,10 +32,7 @@ pub struct DefPathTable { } impl DefPathTable { - fn allocate(&mut self, - key: DefKey, - def_path_hash: DefPathHash) - -> DefIndex { + fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex { let index = { let index = DefIndex::from(self.index_to_key.len()); debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); @@ -63,21 +60,11 @@ impl DefPathTable { hash } - pub fn add_def_path_hashes_to(&self, - cnum: CrateNum, - out: &mut FxHashMap) { - out.extend( - self.def_path_hashes - .iter() - .enumerate() - .map(|(index, &hash)| { - let def_id = DefId { - krate: cnum, - index: DefIndex::from(index), - }; - (hash, def_id) - }) - ); + pub fn add_def_path_hashes_to(&self, cnum: CrateNum, out: &mut FxHashMap) { + out.extend(self.def_path_hashes.iter().enumerate().map(|(index, &hash)| { + let def_id = DefId { krate: cnum, index: DefIndex::from(index) }; + (hash, def_id) + })); } pub fn size(&self) -> usize { @@ -105,7 +92,7 @@ pub struct Definitions { /// we know what parent node that fragment should be attached to thanks to this table. invocation_parents: FxHashMap, /// Indices of unnamed struct or variant fields with unresolved attributes. - pub placeholder_field_indices: NodeMap, + placeholder_field_indices: NodeMap, } /// A unique identifier that we can use to lookup a definition @@ -129,10 +116,7 @@ impl DefKey { 0u8.hash(&mut hasher); parent_hash.hash(&mut hasher); - let DisambiguatedDefPathData { - ref data, - disambiguator, - } = self.disambiguated_data; + let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data; ::std::mem::discriminant(data).hash(&mut hasher); if let Some(name) = data.get_opt_name() { @@ -146,9 +130,10 @@ impl DefKey { DefPathHash(hasher.finish()) } - fn root_parent_stable_hash(crate_name: &str, - crate_disambiguator: CrateDisambiguator) - -> DefPathHash { + fn root_parent_stable_hash( + crate_name: &str, + crate_disambiguator: CrateDisambiguator, + ) -> DefPathHash { let mut hasher = StableHasher::new(); // Disambiguate this from a regular `DefPath` hash; see `compute_stable_hash()` above. 1u8.hash(&mut hasher); @@ -167,7 +152,7 @@ impl DefKey { #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub struct DisambiguatedDefPathData { pub data: DefPathData, - pub disambiguator: u32 + pub disambiguator: u32, } #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] @@ -184,10 +169,9 @@ impl DefPath { self.krate == LOCAL_CRATE } - pub fn make(krate: CrateNum, - start_index: DefIndex, - mut get_key: FN) -> DefPath - where FN: FnMut(DefIndex) -> DefKey + pub fn make(krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefPath + where + FN: FnMut(DefIndex) -> DefKey, { let mut data = vec![]; let mut index = Some(start_index); @@ -218,11 +202,7 @@ impl DefPath { let mut s = String::with_capacity(self.data.len() * 16); for component in &self.data { - write!(s, - "::{}[{}]", - component.data.as_symbol(), - component.disambiguator) - .unwrap(); + write!(s, "::{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap(); } s @@ -231,7 +211,8 @@ impl DefPath { /// Returns a filename-friendly string for the `DefPath`, with the /// crate-prefix. pub fn to_string_friendly(&self, crate_imported_name: F) -> String - where F: FnOnce(CrateNum) -> Symbol + where + F: FnOnce(CrateNum) -> Symbol, { let crate_name_str = crate_imported_name(self.krate).as_str(); let mut s = String::with_capacity(crate_name_str.len() + self.data.len() * 16); @@ -242,11 +223,7 @@ impl DefPath { if component.disambiguator == 0 { write!(s, "::{}", component.data.as_symbol()).unwrap(); } else { - write!(s, - "{}[{}]", - component.data.as_symbol(), - component.disambiguator) - .unwrap(); + write!(s, "{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap(); } } @@ -266,11 +243,7 @@ impl DefPath { if component.disambiguator == 0 { write!(s, "{}", component.data.as_symbol()).unwrap(); } else { - write!(s, - "{}[{}]", - component.data.as_symbol(), - component.disambiguator) - .unwrap(); + write!(s, "{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap(); } } s @@ -281,14 +254,12 @@ impl DefPath { pub enum DefPathData { // Root: these should only be used for the root nodes, because // they are treated specially by the `def_path` function. - /// The crate root (marker). CrateRoot, // Catch-all for random `DefId` things like `DUMMY_NODE_ID`. Misc, // Different kinds of items and item-like things: - /// An impl. Impl, /// Something in the type namespace. @@ -303,25 +274,29 @@ pub enum DefPathData { ClosureExpr, // Subportions of items: - /// Implicit constructor for a unit or tuple-like struct or enum variant. Ctor, /// A constant expression (see `{ast,hir}::AnonConst`). AnonConst, /// An `impl Trait` type node. ImplTrait, - /// Identifies a piece of crate metadata that is global to a whole crate - /// (as opposed to just one item). `GlobalMetaData` components are only - /// supposed to show up right below the crate root. - GlobalMetaData(Symbol), } -#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, - RustcEncodable, RustcDecodable)] +#[derive( + Copy, + Clone, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + Debug, + RustcEncodable, + RustcDecodable, + HashStable, +)] pub struct DefPathHash(pub Fingerprint); -impl_stable_hash_for!(tuple_struct DefPathHash { fingerprint }); - impl Borrow for DefPathHash { #[inline] fn borrow(&self) -> &Fingerprint { @@ -387,11 +362,7 @@ impl Definitions { pub fn as_local_hir_id(&self, def_id: DefId) -> Option { if def_id.krate == LOCAL_CRATE { let hir_id = self.def_index_to_hir_id(def_id.index); - if hir_id != hir::DUMMY_HIR_ID { - Some(hir_id) - } else { - None - } + if hir_id != hir::DUMMY_HIR_ID { Some(hir_id) } else { None } } else { None } @@ -420,20 +391,20 @@ impl Definitions { } /// Adds a root definition (no parent) and a few other reserved definitions. - pub fn create_root_def(&mut self, - crate_name: &str, - crate_disambiguator: CrateDisambiguator) - -> DefIndex { + pub fn create_root_def( + &mut self, + crate_name: &str, + crate_disambiguator: CrateDisambiguator, + ) -> DefIndex { let key = DefKey { parent: None, disambiguated_data: DisambiguatedDefPathData { data: DefPathData::CrateRoot, - disambiguator: 0 - } + disambiguator: 0, + }, }; - let parent_hash = DefKey::root_parent_stable_hash(crate_name, - crate_disambiguator); + let parent_hash = DefKey::root_parent_stable_hash(crate_name, crate_disambiguator); let def_path_hash = key.compute_stable_hash(parent_hash); // Create the definition. @@ -444,28 +415,30 @@ impl Definitions { self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); self.set_invocation_parent(ExpnId::root(), root_index); - // Allocate some other `DefIndex`es that always must exist. - GlobalMetaDataKind::allocate_def_indices(self); - root_index } /// Adds a definition with a parent definition. - pub fn create_def_with_parent(&mut self, - parent: DefIndex, - node_id: ast::NodeId, - data: DefPathData, - expn_id: ExpnId, - span: Span) - -> DefIndex { - debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", - parent, node_id, data); - - assert!(!self.node_to_def_index.contains_key(&node_id), - "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", - node_id, - data, - self.table.def_key(self.node_to_def_index[&node_id])); + pub fn create_def_with_parent( + &mut self, + parent: DefIndex, + node_id: ast::NodeId, + data: DefPathData, + expn_id: ExpnId, + span: Span, + ) -> DefIndex { + debug!( + "create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", + parent, node_id, data + ); + + assert!( + !self.node_to_def_index.contains_key(&node_id), + "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + node_id, + data, + self.table.def_key(self.node_to_def_index[&node_id]) + ); // The root node must be created with `create_root_def()`. assert!(data != DefPathData::CrateRoot); @@ -480,9 +453,7 @@ impl Definitions { let key = DefKey { parent: Some(parent), - disambiguated_data: DisambiguatedDefPathData { - data, disambiguator - } + disambiguated_data: DisambiguatedDefPathData { data, disambiguator }, }; let parent_hash = self.table.def_path_hash(parent); @@ -517,10 +488,11 @@ impl Definitions { /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during /// AST to HIR lowering. - pub fn init_node_id_to_hir_id_mapping(&mut self, - mapping: IndexVec) { - assert!(self.node_to_hir_id.is_empty(), - "trying to initialize `NodeId` -> `HirId` mapping twice"); + pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec) { + assert!( + self.node_to_hir_id.is_empty(), + "trying to initialize `NodeId` -> `HirId` mapping twice" + ); self.node_to_hir_id = mapping; } @@ -559,32 +531,16 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(name) | - ValueNs(name) | - MacroNs(name) | - LifetimeNs(name) | - GlobalMetaData(name) => Some(name), - - Impl | - CrateRoot | - Misc | - ClosureExpr | - Ctor | - AnonConst | - ImplTrait => None + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + + Impl | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => None, } } pub fn as_symbol(&self) -> Symbol { use self::DefPathData::*; match *self { - TypeNs(name) | - ValueNs(name) | - MacroNs(name) | - LifetimeNs(name) | - GlobalMetaData(name) => { - name - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => name, // Note that this does not show up in user print-outs. CrateRoot => sym::double_braced_crate, Impl => sym::double_braced_impl, @@ -600,78 +556,3 @@ impl DefPathData { self.as_symbol().to_string() } } - -// We define the `GlobalMetaDataKind` enum with this macro because we want to -// make sure that we exhaustively iterate over all variants when registering -// the corresponding `DefIndex`es in the `DefTable`. -macro_rules! define_global_metadata_kind { - (pub enum GlobalMetaDataKind { - $($variant:ident),* - }) => ( - pub enum GlobalMetaDataKind { - $($variant),* - } - - impl GlobalMetaDataKind { - fn allocate_def_indices(definitions: &mut Definitions) { - $({ - let instance = GlobalMetaDataKind::$variant; - definitions.create_def_with_parent( - CRATE_DEF_INDEX, - ast::DUMMY_NODE_ID, - DefPathData::GlobalMetaData(instance.name()), - ExpnId::root(), - DUMMY_SP - ); - - // Make sure calling `def_index` does not crash. - instance.def_index(&definitions.table); - })* - } - - pub fn def_index(&self, def_path_table: &DefPathTable) -> DefIndex { - let def_key = DefKey { - parent: Some(CRATE_DEF_INDEX), - disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::GlobalMetaData(self.name()), - disambiguator: 0, - } - }; - - // These `DefKey`s are all right after the root, - // so a linear search is fine. - let index = def_path_table.index_to_key - .iter() - .position(|k| *k == def_key) - .unwrap(); - - DefIndex::from(index) - } - - fn name(&self) -> Symbol { - - let string = match *self { - $( - GlobalMetaDataKind::$variant => { - concat!("{{GlobalMetaData::", stringify!($variant), "}}") - } - )* - }; - - Symbol::intern(string) - } - } - ) -} - -define_global_metadata_kind!(pub enum GlobalMetaDataKind { - Krate, - CrateDeps, - DylibDependencyFormats, - LangItems, - LangItemsMissing, - NativeLibraries, - SourceMap, - Impls, - ExportedSymbols -}); diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index b66c2ce117..b68e195f29 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,29 +1,27 @@ use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; -use crate::hir::{self, intravisit, HirId, ItemLocalId}; use crate::hir::itemlikevisit::ItemLikeVisitor; +use crate::hir::{self, intravisit, HirId, ItemLocalId}; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::{Lock, ParallelIterator, par_iter}; +use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; -pub fn check_crate(hir_map: &hir::map::Map<'_>) { +pub fn check_crate(hir_map: &hir::map::Map<'_>, sess: &rustc_session::Session) { hir_map.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { let local_def_id = hir_map.local_def_id(*module_id); - hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor { - hir_map, - errors: &errors, - }); + hir_map.visit_item_likes_in_module( + local_def_id, + &mut OuterVisitor { hir_map, errors: &errors }, + ); }); let errors = errors.into_inner(); if !errors.is_empty() { - let message = errors - .iter() - .fold(String::new(), |s1, s2| s1 + "\n" + s2); - bug!("{}", message); + let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); + sess.delay_span_bug(syntax_pos::DUMMY_SP, &message); } } @@ -40,9 +38,7 @@ struct OuterVisitor<'a, 'hir> { } impl<'a, 'hir> OuterVisitor<'a, 'hir> { - fn new_inner_visitor(&self, - hir_map: &'a hir::map::Map<'hir>) - -> HirIdValidator<'a, 'hir> { + fn new_inner_visitor(&self, hir_map: &'a hir::map::Map<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { hir_map, owner_def_index: None, @@ -76,9 +72,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.errors.lock().push(f()); } - fn check)>(&mut self, - hir_id: HirId, - walk: F) { + fn check)>(&mut self, hir_id: HirId, walk: F) { assert!(self.owner_def_index.is_none()); let owner_def_index = self.hir_map.local_def_id(hir_id).index; self.owner_def_index = Some(owner_def_index); @@ -89,55 +83,54 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } // There's always at least one entry for the owning item itself - let max = self.hir_ids_seen - .iter() - .map(|local_id| local_id.as_usize()) - .max() - .expect("owning item has no entry"); + let max = self + .hir_ids_seen + .iter() + .map(|local_id| local_id.as_usize()) + .max() + .expect("owning item has no entry"); if max != self.hir_ids_seen.len() - 1 { // Collect the missing ItemLocalIds - let missing: Vec<_> = (0 ..= max as u32) - .filter(|&i| !self.hir_ids_seen.contains(&ItemLocalId::from_u32(i))) - .collect(); + let missing: Vec<_> = (0..=max as u32) + .filter(|&i| !self.hir_ids_seen.contains(&ItemLocalId::from_u32(i))) + .collect(); // Try to map those to something more useful let mut missing_items = Vec::with_capacity(missing.len()); for local_id in missing { - let hir_id = HirId { - owner: owner_def_index, - local_id: ItemLocalId::from_u32(local_id), - }; + let hir_id = + HirId { owner: owner_def_index, local_id: ItemLocalId::from_u32(local_id) }; trace!("missing hir id {:#?}", hir_id); - missing_items.push(format!("[local_id: {}, node:{}]", - local_id, - self.hir_map.node_to_string(hir_id))); + missing_items.push(format!( + "[local_id: {}, node:{}]", + local_id, + self.hir_map.node_to_string(hir_id) + )); } - self.error(|| format!( - "ItemLocalIds not assigned densely in {}. \ + self.error(|| { + format!( + "ItemLocalIds not assigned densely in {}. \ Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", - self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), - max, - missing_items, - self.hir_ids_seen - .iter() - .map(|&local_id| HirId { - owner: owner_def_index, - local_id, - }) - .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) - .collect::>())); + self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), + max, + missing_items, + self.hir_ids_seen + .iter() + .map(|&local_id| HirId { owner: owner_def_index, local_id }) + .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) + .collect::>() + ) + }); } } } impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { - - fn nested_visit_map<'this>(&'this mut self) - -> intravisit::NestedVisitorMap<'this, 'hir> { + fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'hir> { intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) } @@ -145,17 +138,24 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { let owner = self.owner_def_index.expect("no owner_def_index"); if hir_id == hir::DUMMY_HIR_ID { - self.error(|| format!("HirIdValidator: HirId {:?} is invalid", - self.hir_map.node_to_string(hir_id))); + self.error(|| { + format!( + "HirIdValidator: HirId {:?} is invalid", + self.hir_map.node_to_string(hir_id) + ) + }); return; } if owner != hir_id.owner { - self.error(|| format!( - "HirIdValidator: The recorded owner of {} is {} instead of {}", - self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), - self.hir_map.def_path(DefId::local(owner)).to_string_no_crate())); + self.error(|| { + format!( + "HirIdValidator: The recorded owner of {} is {} instead of {}", + self.hir_map.node_to_string(hir_id), + self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), + self.hir_map.def_path(DefId::local(owner)).to_string_no_crate() + ) + }); } self.hir_ids_seen.insert(hir_id.local_id); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index acadd77cc3..8cd12ead65 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1,23 +1,22 @@ use self::collector::NodeCollector; -pub use self::def_collector::DefCollector; pub use self::definitions::{ - Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash + DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData, }; -use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; -use crate::hir::*; -use crate::hir::DefKind; -use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId}; +use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; +use crate::hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use crate::hir::itemlikevisit::ItemLikeVisitor; use crate::hir::print::Nested; +use crate::hir::DefKind; +use crate::hir::*; use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; -use crate::util::nodemap::FxHashMap; use crate::util::common::time; +use crate::util::nodemap::FxHashMap; -use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; use rustc_index::vec::IndexVec; +use rustc_target::spec::abi::Abi; use syntax::ast::{self, Name, NodeId}; use syntax::source_map::Spanned; use syntax_pos::hygiene::MacroKind; @@ -25,7 +24,6 @@ use syntax_pos::{Span, DUMMY_SP}; pub mod blocks; mod collector; -mod def_collector; pub mod definitions; mod hir_id_validator; @@ -47,33 +45,46 @@ impl<'hir> Entry<'hir> { fn fn_decl(&self) -> Option<&'hir FnDecl> { match self.node { - Node::Item(ref item) => { - match item.kind { - ItemKind::Fn(ref fn_decl, _, _, _) => Some(fn_decl), - _ => None, - } - } + Node::Item(ref item) => match item.kind { + ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), + _ => None, + }, - Node::TraitItem(ref item) => { - match item.kind { - TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl), - _ => None - } - } + Node::TraitItem(ref item) => match item.kind { + TraitItemKind::Method(ref sig, _) => Some(&sig.decl), + _ => None, + }, - Node::ImplItem(ref item) => { - match item.kind { - ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl), - _ => None, - } - } + Node::ImplItem(ref item) => match item.kind { + ImplItemKind::Method(ref sig, _) => Some(&sig.decl), + _ => None, + }, - Node::Expr(ref expr) => { - match expr.kind { - ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), - _ => None, - } - } + Node::Expr(ref expr) => match expr.kind { + ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), + _ => None, + }, + + _ => None, + } + } + + fn fn_sig(&self) -> Option<&'hir FnSig> { + match &self.node { + Node::Item(item) => match &item.kind { + ItemKind::Fn(sig, _, _) => Some(sig), + _ => None, + }, + + Node::TraitItem(item) => match &item.kind { + TraitItemKind::Method(sig, _) => Some(sig), + _ => None, + }, + + Node::ImplItem(item) => match &item.kind { + ImplItemKind::Method(sig, _) => Some(sig), + _ => None, + }, _ => None, } @@ -81,41 +92,32 @@ impl<'hir> Entry<'hir> { fn associated_body(self) -> Option { match self.node { - Node::Item(item) => { - match item.kind { - ItemKind::Const(_, body) | - ItemKind::Static(.., body) | - ItemKind::Fn(_, _, _, body) => Some(body), - _ => None, + Node::Item(item) => match item.kind { + ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => { + Some(body) } - } + _ => None, + }, - Node::TraitItem(item) => { - match item.kind { - TraitItemKind::Const(_, Some(body)) | - TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), - _ => None - } - } + Node::TraitItem(item) => match item.kind { + TraitItemKind::Const(_, Some(body)) + | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), + _ => None, + }, - Node::ImplItem(item) => { - match item.kind { - ImplItemKind::Const(_, body) | - ImplItemKind::Method(_, body) => Some(body), - _ => None, - } - } + Node::ImplItem(item) => match item.kind { + ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), + _ => None, + }, Node::AnonConst(constant) => Some(constant.body), - Node::Expr(expr) => { - match expr.kind { - ExprKind::Closure(.., body, _, _) => Some(body), - _ => None, - } - } + Node::Expr(expr) => match expr.kind { + ExprKind::Closure(.., body, _, _) => Some(body), + _ => None, + }, - _ => None + _ => None, } } @@ -135,10 +137,7 @@ pub struct Forest { impl Forest { pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest { - Forest { - krate, - dep_graph: dep_graph.clone(), - } + Forest { krate, dep_graph: dep_graph.clone() } } pub fn krate(&self) -> &Crate { @@ -175,7 +174,7 @@ pub struct Map<'hir> { map: HirEntryMap<'hir>, - definitions: &'hir Definitions, + definitions: Definitions, /// The reverse mapping of `node_to_hir_id`. hir_to_node_id: FxHashMap, @@ -188,10 +187,7 @@ struct ParentHirIterator<'map> { impl<'map> ParentHirIterator<'map> { fn new(current_id: HirId, map: &'map Map<'map>) -> ParentHirIterator<'map> { - ParentHirIterator { - current_id, - map, - } + ParentHirIterator { current_id, map } } } @@ -202,7 +198,8 @@ impl<'map> Iterator for ParentHirIterator<'map> { if self.current_id == CRATE_HIR_ID { return None; } - loop { // There are nodes that do not have entries, so we need to skip them. + loop { + // There are nodes that do not have entries, so we need to skip them. let parent_id = self.map.get_parent_node(self.current_id); if parent_id == self.current_id { @@ -242,8 +239,8 @@ impl<'hir> Map<'hir> { } #[inline] - pub fn definitions(&self) -> &'hir Definitions { - self.definitions + pub fn definitions(&self) -> &Definitions { + &self.definitions } pub fn def_key(&self, def_id: DefId) -> DefKey { @@ -252,9 +249,7 @@ impl<'hir> Map<'hir> { } pub fn def_path_from_hir_id(&self, id: HirId) -> Option { - self.opt_local_def_id(id).map(|def_id| { - self.def_path(def_id) - }) + self.opt_local_def_id(id).map(|def_id| self.def_path(def_id)) } pub fn def_path(&self, def_id: DefId) -> DefPath { @@ -266,16 +261,22 @@ impl<'hir> Map<'hir> { pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId { self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| { let hir_id = self.node_to_hir_id(node); - bug!("local_def_id_from_node_id: no entry for `{}`, which has a map of `{:?}`", - node, self.find_entry(hir_id)) + bug!( + "local_def_id_from_node_id: no entry for `{}`, which has a map of `{:?}`", + node, + self.find_entry(hir_id) + ) }) } #[inline] pub fn local_def_id(&self, hir_id: HirId) -> DefId { self.opt_local_def_id(hir_id).unwrap_or_else(|| { - bug!("local_def_id: no entry for `{:?}`, which has a map of `{:?}`", - hir_id, self.find_entry(hir_id)) + bug!( + "local_def_id: no entry for `{:?}`, which has a map of `{:?}`", + hir_id, + self.find_entry(hir_id) + ) }) } @@ -321,55 +322,43 @@ impl<'hir> Map<'hir> { } pub fn def_kind(&self, hir_id: HirId) -> Option { - let node = if let Some(node) = self.find(hir_id) { - node - } else { - return None - }; + let node = if let Some(node) = self.find(hir_id) { node } else { return None }; Some(match node { - Node::Item(item) => { - match item.kind { - ItemKind::Static(..) => DefKind::Static, - ItemKind::Const(..) => DefKind::Const, - ItemKind::Fn(..) => DefKind::Fn, - ItemKind::Mod(..) => DefKind::Mod, - ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, - ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Enum(..) => DefKind::Enum, - ItemKind::Struct(..) => DefKind::Struct, - ItemKind::Union(..) => DefKind::Union, - ItemKind::Trait(..) => DefKind::Trait, - ItemKind::TraitAlias(..) => DefKind::TraitAlias, - ItemKind::ExternCrate(_) | - ItemKind::Use(..) | - ItemKind::ForeignMod(..) | - ItemKind::GlobalAsm(..) | - ItemKind::Impl(..) => return None, - } - } - Node::ForeignItem(item) => { - match item.kind { - ForeignItemKind::Fn(..) => DefKind::Fn, - ForeignItemKind::Static(..) => DefKind::Static, - ForeignItemKind::Type => DefKind::ForeignTy, - } - } - Node::TraitItem(item) => { - match item.kind { - TraitItemKind::Const(..) => DefKind::AssocConst, - TraitItemKind::Method(..) => DefKind::Method, - TraitItemKind::Type(..) => DefKind::AssocTy, - } - } - Node::ImplItem(item) => { - match item.kind { - ImplItemKind::Const(..) => DefKind::AssocConst, - ImplItemKind::Method(..) => DefKind::Method, - ImplItemKind::TyAlias(..) => DefKind::AssocTy, - ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy, - } - } + Node::Item(item) => match item.kind { + ItemKind::Static(..) => DefKind::Static, + ItemKind::Const(..) => DefKind::Const, + ItemKind::Fn(..) => DefKind::Fn, + ItemKind::Mod(..) => DefKind::Mod, + ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, + ItemKind::TyAlias(..) => DefKind::TyAlias, + ItemKind::Enum(..) => DefKind::Enum, + ItemKind::Struct(..) => DefKind::Struct, + ItemKind::Union(..) => DefKind::Union, + ItemKind::Trait(..) => DefKind::Trait, + ItemKind::TraitAlias(..) => DefKind::TraitAlias, + ItemKind::ExternCrate(_) + | ItemKind::Use(..) + | ItemKind::ForeignMod(..) + | ItemKind::GlobalAsm(..) + | ItemKind::Impl(..) => return None, + }, + Node::ForeignItem(item) => match item.kind { + ForeignItemKind::Fn(..) => DefKind::Fn, + ForeignItemKind::Static(..) => DefKind::Static, + ForeignItemKind::Type => DefKind::ForeignTy, + }, + Node::TraitItem(item) => match item.kind { + TraitItemKind::Const(..) => DefKind::AssocConst, + TraitItemKind::Method(..) => DefKind::Method, + TraitItemKind::Type(..) => DefKind::AssocTy, + }, + Node::ImplItem(item) => match item.kind { + ImplItemKind::Const(..) => DefKind::AssocConst, + ImplItemKind::Method(..) => DefKind::Method, + ImplItemKind::TyAlias(..) => DefKind::AssocTy, + ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy, + }, Node::Variant(_) => DefKind::Variant, Node::Ctor(variant_data) => { // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`? @@ -383,30 +372,28 @@ impl<'hir> Map<'hir> { }; DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data)) } - Node::AnonConst(_) | - Node::Field(_) | - Node::Expr(_) | - Node::Stmt(_) | - Node::PathSegment(_) | - Node::Ty(_) | - Node::TraitRef(_) | - Node::Pat(_) | - Node::Binding(_) | - Node::Local(_) | - Node::Param(_) | - Node::Arm(_) | - Node::Lifetime(_) | - Node::Visibility(_) | - Node::Block(_) | - Node::Crate => return None, + Node::AnonConst(_) + | Node::Field(_) + | Node::Expr(_) + | Node::Stmt(_) + | Node::PathSegment(_) + | Node::Ty(_) + | Node::TraitRef(_) + | Node::Pat(_) + | Node::Binding(_) + | Node::Local(_) + | Node::Param(_) + | Node::Arm(_) + | Node::Lifetime(_) + | Node::Visibility(_) + | Node::Block(_) + | Node::Crate => return None, Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang), - Node::GenericParam(param) => { - match param.kind { - GenericParamKind::Lifetime { .. } => return None, - GenericParamKind::Type { .. } => DefKind::TyParam, - GenericParamKind::Const { .. } => DefKind::ConstParam, - } - } + Node::GenericParam(param) => match param.kind { + GenericParamKind::Lifetime { .. } => return None, + GenericParamKind::Type { .. } => DefKind::TyParam, + GenericParamKind::Const { .. } => DefKind::ConstParam, + }, }) } @@ -450,6 +437,14 @@ impl<'hir> Map<'hir> { } } + pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig> { + if let Some(entry) = self.find_entry(hir_id) { + entry.fn_sig() + } else { + bug!("no entry for hir_id `{}`", hir_id) + } + } + /// Returns the `HirId` that corresponds to the definition of /// which this is the body of, i.e., a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. @@ -482,48 +477,43 @@ impl<'hir> Map<'hir> { /// Given a body owner's id, returns the `BodyId` associated with it. pub fn body_owned_by(&self, id: HirId) -> BodyId { self.maybe_body_owned_by(id).unwrap_or_else(|| { - span_bug!(self.span(id), "body_owned_by: {} has no associated body", - self.node_to_string(id)); + span_bug!( + self.span(id), + "body_owned_by: {} has no associated body", + self.node_to_string(id) + ); }) } pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind { match self.get(id) { - Node::Item(&Item { kind: ItemKind::Const(..), .. }) | - Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) | - Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) | - Node::AnonConst(_) => { - BodyOwnerKind::Const - } - Node::Ctor(..) | - Node::Item(&Item { kind: ItemKind::Fn(..), .. }) | - Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. }) | - Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => { - BodyOwnerKind::Fn - } - Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => { - BodyOwnerKind::Static(m) - } - Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => { - BodyOwnerKind::Closure - } + Node::Item(&Item { kind: ItemKind::Const(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) + | Node::AnonConst(_) => BodyOwnerKind::Const, + Node::Ctor(..) + | Node::Item(&Item { kind: ItemKind::Fn(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. }) + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => BodyOwnerKind::Fn, + Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m), + Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure, node => bug!("{:#?} is not a body node", node), } } pub fn ty_param_owner(&self, id: HirId) -> HirId { match self.get(id) { - Node::Item(&Item { kind: ItemKind::Trait(..), .. }) | - Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => id, + Node::Item(&Item { kind: ItemKind::Trait(..), .. }) + | Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => id, Node::GenericParam(_) => self.get_parent_node(id), - _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)) + _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)), } } pub fn ty_param_name(&self, id: HirId) -> Name { match self.get(id) { - Node::Item(&Item { kind: ItemKind::Trait(..), .. }) | - Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => kw::SelfUpper, + Node::Item(&Item { kind: ItemKind::Trait(..), .. }) + | Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => kw::SelfUpper, Node::GenericParam(param) => param.name.ident().name, _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)), } @@ -551,18 +541,15 @@ impl<'hir> Map<'hir> { let hir_id = self.as_local_hir_id(module).unwrap(); self.read(hir_id); match self.find_entry(hir_id).unwrap().node { - Node::Item(&Item { - span, - kind: ItemKind::Mod(ref m), - .. - }) => (m, span, hir_id), + Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id), Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id), node => panic!("not a module: {:?}", node), } } pub fn visit_item_likes_in_module(&self, module: DefId, visitor: &mut V) - where V: ItemLikeVisitor<'hir> + where + V: ItemLikeVisitor<'hir>, { let hir_id = self.as_local_hir_id(module).unwrap(); @@ -590,8 +577,7 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. pub fn get(&self, id: HirId) -> Node<'hir> { // read recorded by `find` - self.find(id).unwrap_or_else(|| - bug!("couldn't find hir id {} in the HIR map", id)) + self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id)) } pub fn get_if_local(&self, id: DefId) -> Option> { @@ -599,37 +585,29 @@ impl<'hir> Map<'hir> { } pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics> { - self.get_if_local(id).and_then(|node| { - match node { - Node::ImplItem(ref impl_item) => Some(&impl_item.generics), - Node::TraitItem(ref trait_item) => Some(&trait_item.generics), - Node::Item(ref item) => { - match item.kind { - ItemKind::Fn(_, _, ref generics, _) | - ItemKind::TyAlias(_, ref generics) | - ItemKind::Enum(_, ref generics) | - ItemKind::Struct(_, ref generics) | - ItemKind::Union(_, ref generics) | - ItemKind::Trait(_, _, ref generics, ..) | - ItemKind::TraitAlias(ref generics, _) | - ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics), - _ => None, - } - } + self.get_if_local(id).and_then(|node| match node { + Node::ImplItem(ref impl_item) => Some(&impl_item.generics), + Node::TraitItem(ref trait_item) => Some(&trait_item.generics), + Node::Item(ref item) => match item.kind { + ItemKind::Fn(_, ref generics, _) + | ItemKind::TyAlias(_, ref generics) + | ItemKind::Enum(_, ref generics) + | ItemKind::Struct(_, ref generics) + | ItemKind::Union(_, ref generics) + | ItemKind::Trait(_, _, ref generics, ..) + | ItemKind::TraitAlias(ref generics, _) + | ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics), _ => None, - } + }, + _ => None, }) } /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { - let result = self.find_entry(hir_id).and_then(|entry| { - if let Node::Crate = entry.node { - None - } else { - Some(entry.node) - } - }); + let result = self + .find_entry(hir_id) + .and_then(|entry| if let Node::Crate = entry.node { None } else { Some(entry.node) }); if result.is_some() { self.read(hir_id); } @@ -653,9 +631,7 @@ impl<'hir> Map<'hir> { self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); } - self.find_entry(hir_id) - .and_then(|x| x.parent_node()) - .unwrap_or(hir_id) + self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id) } /// Checks if the node is an argument. An argument is a local variable whose @@ -666,15 +642,11 @@ impl<'hir> Map<'hir> { _ => return false, } match self.find(self.get_parent_node(id)) { - Some(Node::Item(_)) | - Some(Node::TraitItem(_)) | - Some(Node::ImplItem(_)) => true, - Some(Node::Expr(e)) => { - match e.kind { - ExprKind::Closure(..) => true, - _ => false, - } - } + Some(Node::Item(_)) | Some(Node::TraitItem(_)) | Some(Node::ImplItem(_)) => true, + Some(Node::Expr(e)) => match e.kind { + ExprKind::Closure(..) => true, + _ => false, + }, _ => false, } } @@ -684,27 +656,14 @@ impl<'hir> Map<'hir> { pub fn is_const_context(&self, hir_id: HirId) -> bool { let parent_id = self.get_parent_item(hir_id); match self.get(parent_id) { - Node::Item(&Item { - kind: ItemKind::Const(..), - .. - }) - | Node::TraitItem(&TraitItem { - kind: TraitItemKind::Const(..), - .. - }) - | Node::ImplItem(&ImplItem { - kind: ImplItemKind::Const(..), - .. - }) + Node::Item(&Item { kind: ItemKind::Const(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) | Node::AnonConst(_) - | Node::Item(&Item { - kind: ItemKind::Static(..), - .. - }) => true, - Node::Item(&Item { - kind: ItemKind::Fn(_, header, ..), - .. - }) => header.constness == Constness::Const, + | Node::Item(&Item { kind: ItemKind::Static(..), .. }) => true, + Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => { + sig.header.constness == Constness::Const + } _ => false, } } @@ -712,8 +671,8 @@ impl<'hir> Map<'hir> { /// Wether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { match self.lookup(hir_id) { - Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) | - Some(Entry { node: Node::Crate, .. }) => true, + Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) + | Some(Entry { node: Node::Crate, .. }) => true, _ => false, } } @@ -764,11 +723,11 @@ impl<'hir> Map<'hir> { } } match node { - Node::Item(_) | - Node::ForeignItem(_) | - Node::TraitItem(_) | - Node::Expr(Expr { kind: ExprKind::Closure(..), ..}) | - Node::ImplItem(_) => return Some(hir_id), + Node::Item(_) + | Node::ForeignItem(_) + | Node::TraitItem(_) + | Node::Expr(Expr { kind: ExprKind::Closure(..), .. }) + | Node::ImplItem(_) => return Some(hir_id), Node::Expr(ref expr) => { match expr.kind { // Ignore `return`s on the first iteration @@ -790,11 +749,11 @@ impl<'hir> Map<'hir> { pub fn get_parent_item(&self, hir_id: HirId) -> HirId { for (hir_id, node) in ParentHirIterator::new(hir_id, &self) { match node { - Node::Crate | - Node::Item(_) | - Node::ForeignItem(_) | - Node::TraitItem(_) | - Node::ImplItem(_) => return hir_id, + Node::Crate + | Node::Item(_) + | Node::ForeignItem(_) + | Node::TraitItem(_) + | Node::ImplItem(_) => return hir_id, _ => {} } } @@ -826,10 +785,9 @@ impl<'hir> Map<'hir> { pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&Expr> { for (_, node) in ParentHirIterator::new(hir_id, &self) { match node { - Node::Item(_) | - Node::ForeignItem(_) | - Node::TraitItem(_) | - Node::ImplItem(_) => break, + Node::Item(_) | Node::ForeignItem(_) | Node::TraitItem(_) | Node::ImplItem(_) => { + break; + } Node::Expr(expr) => match expr.kind { ExprKind::Match(_, _, _) => return Some(expr), _ => {} @@ -837,7 +795,7 @@ impl<'hir> Map<'hir> { Node::Stmt(stmt) => match stmt.kind { StmtKind::Local(_) => break, _ => {} - } + }, _ => {} } } @@ -848,35 +806,27 @@ impl<'hir> Map<'hir> { pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option { for (hir_id, node) in ParentHirIterator::new(hir_id, &self) { if match node { - Node::Item(i) => { - match i.kind { - ItemKind::Fn(..) - | ItemKind::Mod(..) - | ItemKind::Enum(..) - | ItemKind::Struct(..) - | ItemKind::Union(..) - | ItemKind::Trait(..) - | ItemKind::Impl(..) => true, - _ => false, - } + Node::Item(i) => match i.kind { + ItemKind::Fn(..) + | ItemKind::Mod(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) + | ItemKind::Trait(..) + | ItemKind::Impl(..) => true, + _ => false, }, - Node::ForeignItem(fi) => { - match fi.kind { - ForeignItemKind::Fn(..) => true, - _ => false, - } + Node::ForeignItem(fi) => match fi.kind { + ForeignItemKind::Fn(..) => true, + _ => false, }, - Node::TraitItem(ti) => { - match ti.kind { - TraitItemKind::Method(..) => true, - _ => false, - } + Node::TraitItem(ti) => match ti.kind { + TraitItemKind::Method(..) => true, + _ => false, }, - Node::ImplItem(ii) => { - match ii.kind { - ImplItemKind::Method(..) => true, - _ => false, - } + Node::ImplItem(ii) => match ii.kind { + ImplItemKind::Method(..) => true, + _ => false, }, Node::Block(_) => true, _ => false, @@ -896,12 +846,10 @@ impl<'hir> Map<'hir> { return CRATE_HIR_ID; } match self.get(scope) { - Node::Item(i) => { - match i.kind { - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {} - _ => break, - } - } + Node::Item(i) => match i.kind { + ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {} + _ => break, + }, Node::Block(_) => {} _ => break, } @@ -917,7 +865,8 @@ impl<'hir> Map<'hir> { let parent = self.get_parent_item(hir_id); if let Some(entry) = self.find_entry(parent) { if let Entry { - node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), .. } = entry + node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), .. + } = entry { self.read(hir_id); // reveals some of the content of a node return nm.abi; @@ -927,38 +876,38 @@ impl<'hir> Map<'hir> { } pub fn expect_item(&self, id: HirId) -> &'hir Item { - match self.find(id) { // read recorded by `find` + match self.find(id) { + // read recorded by `find` Some(Node::Item(item)) => item, - _ => bug!("expected item, found {}", self.node_to_string(id)) + _ => bug!("expected item, found {}", self.node_to_string(id)), } } pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem { match self.find(id) { Some(Node::ImplItem(item)) => item, - _ => bug!("expected impl item, found {}", self.node_to_string(id)) + _ => bug!("expected impl item, found {}", self.node_to_string(id)), } } pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem { match self.find(id) { Some(Node::TraitItem(item)) => item, - _ => bug!("expected trait item, found {}", self.node_to_string(id)) + _ => bug!("expected trait item, found {}", self.node_to_string(id)), } } pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData { match self.find(id) { - Some(Node::Item(i)) => { - match i.kind { - ItemKind::Struct(ref struct_def, _) | - ItemKind::Union(ref struct_def, _) => struct_def, - _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)) + Some(Node::Item(i)) => match i.kind { + ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { + struct_def } - } + _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)), + }, Some(Node::Variant(variant)) => &variant.data, Some(Node::Ctor(data)) => data, - _ => bug!("expected struct or variant, found {}", self.node_to_string(id)) + _ => bug!("expected struct or variant, found {}", self.node_to_string(id)), } } @@ -972,19 +921,20 @@ impl<'hir> Map<'hir> { pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem { match self.find(id) { Some(Node::ForeignItem(item)) => item, - _ => bug!("expected foreign item, found {}", self.node_to_string(id)) + _ => bug!("expected foreign item, found {}", self.node_to_string(id)), } } pub fn expect_expr(&self, id: HirId) -> &'hir Expr { - match self.find(id) { // read recorded by find + match self.find(id) { + // read recorded by find Some(Node::Expr(expr)) => expr, - _ => bug!("expected expr, found {}", self.node_to_string(id)) + _ => bug!("expected expr, found {}", self.node_to_string(id)), } } - pub fn name(&self, id: HirId) -> Name { - match self.get(id) { + pub fn opt_name(&self, id: HirId) -> Option { + Some(match self.get(id) { Node::Item(i) => i.ident.name, Node::ForeignItem(fi) => fi.ident.name, Node::ImplItem(ii) => ii.ident.name, @@ -995,7 +945,14 @@ impl<'hir> Map<'hir> { Node::GenericParam(param) => param.name.ident().name, Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name, Node::Ctor(..) => self.name(self.get_parent_item(id)), - _ => bug!("no name for {}", self.node_to_string(id)) + _ => return None, + }) + } + + pub fn name(&self, id: HirId) -> Name { + match self.opt_name(id) { + Some(name) => name, + None => bug!("no name for {}", self.node_to_string(id)), } } @@ -1020,7 +977,7 @@ impl<'hir> Map<'hir> { // the struct/variant definition. Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)), Some(Node::Crate) => Some(&self.forest.krate.attrs[..]), - _ => None + _ => None, }; attrs.unwrap_or(&[]) } @@ -1033,13 +990,12 @@ impl<'hir> Map<'hir> { // local maps and their index given that they exist. self.map.iter_enumerated().flat_map(move |(owner, local_map)| { // Iterate over each valid entry in the local map. - local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { - // Reconstruct the `HirId` based on the 3 indices we used to find it. - HirId { - owner, - local_id: i, - } - })) + local_map.iter_enumerated().filter_map(move |(i, entry)| { + entry.map(move |_| { + // Reconstruct the `HirId` based on the 3 indices we used to find it. + HirId { owner, local_id: i } + }) + }) }) } @@ -1050,17 +1006,19 @@ impl<'hir> Map<'hir> { /// the iterator will produce node id's for items with paths /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) - -> impl Iterator + 'a { + pub fn nodes_matching_suffix<'a>( + &'a self, + parts: &'a [String], + ) -> impl Iterator + 'a { let nodes = NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), in_which: &parts[..parts.len() - 1], }; - self.all_ids().filter(move |hir| nodes.matches_suffix(*hir)).map(move |hir| { - self.hir_to_node_id(hir) - }) + self.all_ids() + .filter(move |hir| nodes.matches_suffix(*hir)) + .map(move |hir| self.hir_to_node_id(hir)) } pub fn span(&self, hir_id: HirId) -> Span { @@ -1083,17 +1041,16 @@ impl<'hir> Map<'hir> { Some(Node::Pat(pat)) => pat.span, Some(Node::Arm(arm)) => arm.span, Some(Node::Block(block)) => block.span, - Some(Node::Ctor(..)) => match self.find( - self.get_parent_node(hir_id)) - { + Some(Node::Ctor(..)) => match self.find(self.get_parent_node(hir_id)) { Some(Node::Item(item)) => item.span, Some(Node::Variant(variant)) => variant.span, _ => unreachable!(), - } + }, Some(Node::Lifetime(lifetime)) => lifetime.span, Some(Node::GenericParam(param)) => param.span, Some(Node::Visibility(&Spanned { - node: VisibilityKind::Restricted { ref path, .. }, .. + node: VisibilityKind::Restricted { ref path, .. }, + .. })) => path.span, Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v), Some(Node::Local(local)) => local.span, @@ -1165,11 +1122,13 @@ impl<'a> NodesMatchingSuffix<'a> { loop { if let Node::Item(item) = map.find(id)? { if item_is_mod(&item) { - return Some((id, item.ident.name)) + return Some((id, item.ident.name)); } } let parent = map.get_parent_item(id); - if parent == id { return None } + if parent == id { + return None; + } id = parent; } @@ -1206,44 +1165,74 @@ trait Named { fn name(&self) -> Name; } -impl Named for Spanned { fn name(&self) -> Name { self.node.name() } } +impl Named for Spanned { + fn name(&self) -> Name { + self.node.name() + } +} -impl Named for Item { fn name(&self) -> Name { self.ident.name } } -impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } -impl Named for Variant { fn name(&self) -> Name { self.ident.name } } -impl Named for StructField { fn name(&self) -> Name { self.ident.name } } -impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } -impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } +impl Named for Item { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for ForeignItem { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for Variant { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for StructField { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for TraitItem { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for ImplItem { + fn name(&self) -> Name { + self.ident.name + } +} -pub fn map_crate<'hir>(sess: &crate::session::Session, - cstore: &CrateStoreDyn, - forest: &'hir Forest, - definitions: &'hir Definitions) - -> Map<'hir> { +pub fn map_crate<'hir>( + sess: &crate::session::Session, + cstore: &CrateStoreDyn, + forest: &'hir Forest, + definitions: Definitions, +) -> Map<'hir> { let _prof_timer = sess.prof.generic_activity("build_hir_map"); // Build the reverse mapping of `node_to_hir_id`. - let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated() - .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); + let hir_to_node_id = definitions + .node_to_hir_id + .iter_enumerated() + .map(|(node_id, &hir_id)| (hir_id, node_id)) + .collect(); let (map, crate_hash) = { - let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore); - - let mut collector = NodeCollector::root(sess, - &forest.krate, - &forest.dep_graph, - &definitions, - &hir_to_node_id, - hcx); + let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore); + + let mut collector = NodeCollector::root( + sess, + &forest.krate, + &forest.dep_graph, + &definitions, + &hir_to_node_id, + hcx, + ); intravisit::walk_crate(&mut collector, &forest.krate); let crate_disambiguator = sess.local_crate_disambiguator(); let cmdline_args = sess.opts.dep_tracking_hash(); - collector.finalize_and_compute_crate_hash( - crate_disambiguator, - cstore, - cmdline_args - ) + collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args) }; let map = Map { @@ -1256,7 +1245,7 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, }; time(sess, "validate HIR map", || { - hir_id_validator::check_crate(&map); + hir_id_validator::check_crate(&map, sess); }); map @@ -1271,7 +1260,7 @@ impl<'hir> print::PpAnn for Map<'hir> { Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat) + Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat), } } } @@ -1279,39 +1268,38 @@ impl<'hir> print::PpAnn for Map<'hir> { impl<'a> print::State<'a> { pub fn print_node(&mut self, node: Node<'_>) { match node { - Node::Param(a) => self.print_param(&a), - Node::Item(a) => self.print_item(&a), - Node::ForeignItem(a) => self.print_foreign_item(&a), - Node::TraitItem(a) => self.print_trait_item(a), - Node::ImplItem(a) => self.print_impl_item(a), - Node::Variant(a) => self.print_variant(&a), - Node::AnonConst(a) => self.print_anon_const(&a), - Node::Expr(a) => self.print_expr(&a), - Node::Stmt(a) => self.print_stmt(&a), - Node::PathSegment(a) => self.print_path_segment(&a), - Node::Ty(a) => self.print_type(&a), - Node::TraitRef(a) => self.print_trait_ref(&a), - Node::Binding(a) | - Node::Pat(a) => self.print_pat(&a), - Node::Arm(a) => self.print_arm(&a), - Node::Block(a) => { + Node::Param(a) => self.print_param(&a), + Node::Item(a) => self.print_item(&a), + Node::ForeignItem(a) => self.print_foreign_item(&a), + Node::TraitItem(a) => self.print_trait_item(a), + Node::ImplItem(a) => self.print_impl_item(a), + Node::Variant(a) => self.print_variant(&a), + Node::AnonConst(a) => self.print_anon_const(&a), + Node::Expr(a) => self.print_expr(&a), + Node::Stmt(a) => self.print_stmt(&a), + Node::PathSegment(a) => self.print_path_segment(&a), + Node::Ty(a) => self.print_type(&a), + Node::TraitRef(a) => self.print_trait_ref(&a), + Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), + Node::Arm(a) => self.print_arm(&a), + Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(print::INDENT_UNIT); // Head-ibox, will be closed by print-block after `{`. self.ibox(0); self.print_block(&a) } - Node::Lifetime(a) => self.print_lifetime(&a), - Node::Visibility(a) => self.print_visibility(&a), + Node::Lifetime(a) => self.print_lifetime(&a), + Node::Visibility(a) => self.print_visibility(&a), Node::GenericParam(_) => bug!("cannot print Node::GenericParam"), - Node::Field(_) => bug!("cannot print StructField"), + Node::Field(_) => bug!("cannot print StructField"), // These cases do not carry enough information in the // `hir_map` to reconstruct their full structure for pretty // printing. - Node::Ctor(..) => bug!("cannot print isolated Ctor"), - Node::Local(a) => self.print_local_decl(&a), - Node::MacroDef(_) => bug!("cannot print MacroDef"), - Node::Crate => bug!("cannot print Crate"), + Node::Ctor(..) => bug!("cannot print isolated Ctor"), + Node::Local(a) => self.print_local_decl(&a), + Node::MacroDef(_) => bug!("cannot print MacroDef"), + Node::Crate => bug!("cannot print Crate"), } } } @@ -1328,9 +1316,11 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { let def_id = map.local_def_id(id); tcx.def_path_str(def_id) } else if let Some(path) = map.def_path_from_hir_id(id) { - path.data.into_iter().map(|elem| { - elem.data.to_string() - }).collect::>().join("::") + path.data + .into_iter() + .map(|elem| elem.data.to_string()) + .collect::>() + .join("::") } else { String::from("") } @@ -1359,25 +1349,19 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { }; format!("{} {}{}", item_str, path_str(), id_str) } - Some(Node::ForeignItem(_)) => { - format!("foreign item {}{}", path_str(), id_str) - } - Some(Node::ImplItem(ii)) => { - match ii.kind { - ImplItemKind::Const(..) => { - format!("assoc const {} in {}{}", ii.ident, path_str(), id_str) - } - ImplItemKind::Method(..) => { - format!("method {} in {}{}", ii.ident, path_str(), id_str) - } - ImplItemKind::TyAlias(_) => { - format!("assoc type {} in {}{}", ii.ident, path_str(), id_str) - } - ImplItemKind::OpaqueTy(_) => { - format!("assoc opaque type {} in {}{}", ii.ident, path_str(), id_str) - } + Some(Node::ForeignItem(_)) => format!("foreign item {}{}", path_str(), id_str), + Some(Node::ImplItem(ii)) => match ii.kind { + ImplItemKind::Const(..) => { + format!("assoc const {} in {}{}", ii.ident, path_str(), id_str) } - } + ImplItemKind::Method(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str), + ImplItemKind::TyAlias(_) => { + format!("assoc type {} in {}{}", ii.ident, path_str(), id_str) + } + ImplItemKind::OpaqueTy(_) => { + format!("assoc opaque type {} in {}{}", ii.ident, path_str(), id_str) + } + }, Some(Node::TraitItem(ti)) => { let kind = match ti.kind { TraitItemKind::Const(..) => "assoc constant", @@ -1388,66 +1372,30 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { format!("{} {} in {}{}", kind, ti.ident, path_str(), id_str) } Some(Node::Variant(ref variant)) => { - format!("variant {} in {}{}", - variant.ident, - path_str(), id_str) + format!("variant {} in {}{}", variant.ident, path_str(), id_str) } Some(Node::Field(ref field)) => { - format!("field {} in {}{}", - field.ident, - path_str(), id_str) - } - Some(Node::AnonConst(_)) => { - format!("const {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Expr(_)) => { - format!("expr {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Stmt(_)) => { - format!("stmt {}{}", map.hir_to_pretty_string(id), id_str) + format!("field {} in {}{}", field.ident, path_str(), id_str) } + Some(Node::AnonConst(_)) => format!("const {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Expr(_)) => format!("expr {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Stmt(_)) => format!("stmt {}{}", map.hir_to_pretty_string(id), id_str), Some(Node::PathSegment(_)) => { format!("path segment {}{}", map.hir_to_pretty_string(id), id_str) } - Some(Node::Ty(_)) => { - format!("type {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::TraitRef(_)) => { - format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Binding(_)) => { - format!("local {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Pat(_)) => { - format!("pat {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Param(_)) => { - format!("param {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Arm(_)) => { - format!("arm {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Block(_)) => { - format!("block {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Local(_)) => { - format!("local {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Ctor(..)) => { - format!("ctor {}{}", path_str(), id_str) - } - Some(Node::Lifetime(_)) => { - format!("lifetime {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::GenericParam(ref param)) => { - format!("generic_param {:?}{}", param, id_str) - } - Some(Node::Visibility(ref vis)) => { - format!("visibility {:?}{}", vis, id_str) - } - Some(Node::MacroDef(_)) => { - format!("macro {}{}", path_str(), id_str) - } + Some(Node::Ty(_)) => format!("type {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::TraitRef(_)) => format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Binding(_)) => format!("local {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Pat(_)) => format!("pat {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Param(_)) => format!("param {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Arm(_)) => format!("arm {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Block(_)) => format!("block {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Local(_)) => format!("local {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str), + Some(Node::Lifetime(_)) => format!("lifetime {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str), + Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str), + Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str), Some(Node::Crate) => String::from("root_crate"), None => format!("unknown node{}", id_str), } @@ -1458,9 +1406,7 @@ pub fn provide(providers: &mut Providers<'_>) { if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { tcx.hir().def_kind(hir_id) } else { - bug!("calling local def_kind query provider for upstream DefId: {:?}", - def_id - ); + bug!("calling local def_kind query provider for upstream DefId: {:?}", def_id); } }; } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 0edc41e6b4..6b354b0151 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -3,9 +3,7 @@ //! [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html pub use self::BlockCheckMode::*; -pub use self::CaptureClause::*; pub use self::FunctionRetTy::*; -pub use self::Mutability::*; pub use self::PrimTy::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; @@ -23,6 +21,8 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use syntax::source_map::Spanned; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; +pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy}; +pub use syntax::ast::{IsAuto, ImplPolarity, BorrowKind}; use syntax::attr::{InlineAttr, OptimizeAttr}; use syntax::symbol::{Symbol, kw}; use syntax::tokenstream::TokenStream; @@ -1048,35 +1048,18 @@ pub enum PatKind { /// A range pattern (e.g., `1..=2` or `1..2`). Range(P, P, RangeEnd), - /// `[a, b, ..i, y, z]` is represented as: - /// `PatKind::Slice(box [a, b], Some(i), box [y, z])`. + /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`. + /// + /// Here, `slice` is lowered from the syntax `($binding_mode $ident @)? ..`. + /// If `slice` exists, then `after` can be non-empty. + /// + /// The representation for e.g., `[a, b, .., c, d]` is: + /// ``` + /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)]) + /// ``` Slice(HirVec>, Option>, HirVec>), } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, - RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Mutability { - MutMutable, - MutImmutable, -} - -impl Mutability { - /// Returns `MutMutable` only if both `self` and `other` are mutable. - pub fn and(self, other: Self) -> Self { - match self { - MutMutable => other, - MutImmutable => MutImmutable, - } - } - - pub fn invert(self) -> Self { - match self { - MutMutable => MutImmutable, - MutImmutable => MutMutable, - } - } -} - #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum BinOpKind { /// The `+` operator (addition). @@ -1240,7 +1223,7 @@ impl UnOp { } /// A statement. -#[derive(RustcEncodable, RustcDecodable)] +#[derive(RustcEncodable, RustcDecodable, HashStable)] pub struct Stmt { pub hir_id: HirId, pub kind: StmtKind, @@ -1482,7 +1465,7 @@ pub struct Expr { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(Expr, 72); +static_assert_size!(Expr, 64); impl Expr { pub fn precedence(&self) -> ExprPrecedence { @@ -1518,8 +1501,20 @@ impl Expr { } } - pub fn is_place_expr(&self) -> bool { - match self.kind { + // Whether this looks like a place expr, without checking for deref + // adjustments. + // This will return `true` in some potentially surprising cases such as + // `CONSTANT.field`. + pub fn is_syntactic_place_expr(&self) -> bool { + self.is_place_expr(|_| true) + } + + // Whether this is a place expression. + // `allow_projections_from` should return `true` if indexing a field or + // index expression based on the given expression should be considered a + // place expression. + pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool { + match self.kind { ExprKind::Path(QPath::Resolved(_, ref path)) => { match path.res { Res::Local(..) @@ -1529,14 +1524,19 @@ impl Expr { } } + // Type ascription inherits its place expression kind from its + // operand. See: + // https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries ExprKind::Type(ref e, _) => { - e.is_place_expr() + e.is_place_expr(allow_projections_from) } - ExprKind::Unary(UnDeref, _) | - ExprKind::Field(..) | - ExprKind::Index(..) => { - true + ExprKind::Unary(UnDeref, _) => true, + + ExprKind::Field(ref base, _) | + ExprKind::Index(ref base, _) => { + allow_projections_from(base) + || base.is_place_expr(allow_projections_from) } // Partially qualified paths in expressions can only legally @@ -1616,6 +1616,11 @@ pub enum ExprKind { /// and the remaining elements are the rest of the arguments. /// Thus, `x.foo::(a, b, c, d)` is represented as /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`. + /// + /// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with + /// the `hir_id` of the `MethodCall` node itself. + /// + /// [`type_dependent_def_id`]: ../ty/struct.TypeckTables.html#method.type_dependent_def_id MethodCall(P, Span, HirVec), /// A tuple (e.g., `(a, b, c, d)`). Tup(HirVec), @@ -1647,8 +1652,8 @@ pub enum ExprKind { /// The `Span` is the argument block `|...|`. /// /// This may also be a generator literal or an `async block` as indicated by the - /// `Option`. - Closure(CaptureClause, P, BodyId, Span, Option), + /// `Option`. + Closure(CaptureBy, P, BodyId, Span, Option), /// A block (e.g., `'label: { ... }`). Block(P, Option::new` and /// so forth. -#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable, Lift)] pub enum UserType<'tcx> { Ty(Ty<'tcx>), @@ -911,21 +895,6 @@ pub enum UserType<'tcx> { TypeOf(DefId, UserSubsts<'tcx>), } -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for UserType<'tcx> { - (UserType::Ty)(ty), - (UserType::TypeOf)(def, substs), - } -} - -EnumLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for UserType<'a> { - type Lifted = UserType<'tcx>; - (UserType::Ty)(ty), - (UserType::TypeOf)(def, substs), - } -} - impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { let mk = |ty| interners.intern_ty(ty); @@ -986,7 +955,7 @@ impl<'tcx> CommonConsts<'tcx> { CommonConsts { err: mk_const(ty::Const { - val: ConstValue::Scalar(Scalar::zst()), + val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())), ty: types.err, }), } @@ -1026,7 +995,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> { } pub struct GlobalCtxt<'tcx> { - pub arena: WorkerLocal>, + pub arena: &'tcx WorkerLocal>, interners: CtxtInterners<'tcx>, @@ -1097,8 +1066,12 @@ pub struct GlobalCtxt<'tcx> { /// Data layout specification for the current target. pub data_layout: TargetDataLayout, + /// `#[stable]` and `#[unstable]` attributes stability_interner: ShardedHashMap<&'tcx attr::Stability, ()>, + /// `#[rustc_const_stable]` and `#[rustc_const_unstable]` attributes + const_stability_interner: ShardedHashMap<&'tcx attr::ConstStability, ()>, + /// Stores the value of constants (and deduplicates the actual memory) allocation_interner: ShardedHashMap<&'tcx Allocation, ()>, @@ -1115,17 +1088,17 @@ impl<'tcx> TyCtxt<'tcx> { &self.hir_map } - pub fn alloc_steal_mir(self, mir: Body<'tcx>) -> &'tcx Steal> { + pub fn alloc_steal_mir(self, mir: BodyAndCache<'tcx>) -> &'tcx Steal> { self.arena.alloc(Steal::new(mir)) } - pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> - &'tcx Steal>> { + pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> + &'tcx Steal>> { self.arena.alloc(Steal::new(promoted)) } - pub fn intern_promoted(self, promoted: IndexVec>) -> - &'tcx IndexVec> { + pub fn intern_promoted(self, promoted: IndexVec>) -> + &'tcx IndexVec> { self.arena.alloc(promoted) } @@ -1160,6 +1133,12 @@ impl<'tcx> TyCtxt<'tcx> { }) } + pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability { + self.const_stability_interner.intern(stab, |stab| { + self.arena.alloc(stab) + }) + } + pub fn intern_layout(self, layout: LayoutDetails) -> &'tcx LayoutDetails { self.layout_interner.intern(layout, |layout| { self.arena.alloc(layout) @@ -1201,6 +1180,7 @@ impl<'tcx> TyCtxt<'tcx> { local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, + arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, @@ -1256,7 +1236,7 @@ impl<'tcx> TyCtxt<'tcx> { sess: s, lint_store, cstore, - arena: WorkerLocal::new(|_| Arena::default()), + arena, interners, dep_graph, prof: s.prof.clone(), @@ -1299,6 +1279,7 @@ impl<'tcx> TyCtxt<'tcx> { data_layout, layout_interner: Default::default(), stability_interner: Default::default(), + const_stability_interner: Default::default(), allocation_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames.clone()), @@ -1338,7 +1319,11 @@ impl<'tcx> TyCtxt<'tcx> { self.all_crate_nums(LOCAL_CRATE) } - pub fn features(self) -> &'tcx feature_gate::Features { + pub fn allocator_kind(self) -> Option { + self.cstore.allocator_kind() + } + + pub fn features(self) -> &'tcx rustc_feature::Features { self.features_query(LOCAL_CRATE) } @@ -1414,8 +1399,8 @@ impl<'tcx> TyCtxt<'tcx> { // Note that this is *untracked* and should only be used within the query // system if the result is otherwise tracked through queries - pub fn crate_data_as_any(self, cnum: CrateNum) -> &'tcx dyn Any { - self.cstore.crate_data_as_any(cnum) + pub fn cstore_as_any(self) -> &'tcx dyn Any { + self.cstore.as_any() } #[inline(always)] @@ -1552,14 +1537,14 @@ impl<'tcx> TyCtxt<'tcx> { return Some(FreeRegionInfo { def_id: suitable_region_binding_scope, boundregion: bound_region, - is_impl_item: is_impl_item, + is_impl_item, }); } pub fn return_type_impl_trait( &self, scope_def_id: DefId, - ) -> Option> { + ) -> Option<(Ty<'tcx>, Span)> { // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`. let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap(); match self.hir().get(hir_id) { @@ -1580,7 +1565,8 @@ impl<'tcx> TyCtxt<'tcx> { let sig = ret_ty.fn_sig(*self); let output = self.erase_late_bound_regions(&sig.output()); if output.is_impl_trait() { - Some(output) + let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); + Some((output, fn_decl.output.span())) } else { None } @@ -1614,6 +1600,15 @@ impl<'tcx> TyCtxt<'tcx> { pub fn has_strict_asm_symbol_naming(&self) -> bool { self.sess.target.target.arch.contains("nvptx") } + + /// Returns `&'static core::panic::Location<'static>`. + pub fn caller_location_ty(&self) -> Ty<'tcx> { + self.mk_imm_ref( + self.lifetimes.re_static, + self.type_of(self.require_lang_item(PanicLocationLangItem, None)) + .subst(*self, self.mk_substs([self.lifetimes.re_static.into()].iter())), + ) + } } impl<'tcx> GlobalCtxt<'tcx> { @@ -2074,6 +2069,7 @@ impl<'tcx> TyCtxt<'tcx> { println!("InternalSubsts interner: #{}", self.interners.substs.len()); println!("Region interner: #{}", self.interners.region.len()); println!("Stability interner: #{}", self.stability_interner.len()); + println!("Const Stability interner: #{}", self.const_stability_interner.len()); println!("Allocation interner: #{}", self.allocation_interner.len()); println!("Layout interner: #{}", self.layout_interner.len()); } @@ -2410,22 +2406,22 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutMutable}) + self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Mutable}) } #[inline] pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) + self.mk_ref(r, TypeAndMut {ty: ty, mutbl: hir::Mutability::Immutable}) } #[inline] pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutMutable}) + self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Mutable}) } #[inline] pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::MutImmutable}) + self.mk_ptr(TypeAndMut {ty: ty, mutbl: hir::Mutability::Immutable}) } #[inline] @@ -2463,10 +2459,10 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_diverging_default(self) -> Ty<'tcx> { - if self.features().never_type { + if self.features().never_type_fallback { self.types.never } else { - self.intern_tup(&[]) + self.types.unit } } @@ -2516,7 +2512,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_generator(self, id: DefId, generator_substs: SubstsRef<'tcx>, - movability: hir::GeneratorMovability) + movability: hir::Movability) -> Ty<'tcx> { self.mk_ty(Generator(id, generator_substs, movability)) } @@ -2534,7 +2530,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { self.mk_const(ty::Const { - val: ConstValue::Infer(InferConst::Var(v)), + val: ty::ConstKind::Infer(InferConst::Var(v)), ty, }) } @@ -2561,7 +2557,7 @@ impl<'tcx> TyCtxt<'tcx> { ty: Ty<'tcx>, ) -> &'tcx ty::Const<'tcx> { self.mk_const(ty::Const { - val: ConstValue::Infer(ic), + val: ty::ConstKind::Infer(ic), ty, }) } @@ -2579,7 +2575,7 @@ impl<'tcx> TyCtxt<'tcx> { ty: Ty<'tcx> ) -> &'tcx Const<'tcx> { self.mk_const(ty::Const { - val: ConstValue::Param(ParamConst { index, name }), + val: ty::ConstKind::Param(ParamConst { index, name }), ty, }) } @@ -3008,6 +3004,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { let id = tcx.hir().definitions().def_index_to_hir_id(id.index); tcx.stability().local_stability(id) }; + providers.lookup_const_stability = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + let id = tcx.hir().definitions().def_index_to_hir_id(id.index); + tcx.stability().local_const_stability(id) + }; providers.lookup_deprecation_entry = |tcx, id| { assert_eq!(id.krate, LOCAL_CRATE); let id = tcx.hir().definitions().def_index_to_hir_id(id.index); @@ -3021,14 +3022,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { assert_eq!(cnum, LOCAL_CRATE); tcx.arena.alloc_slice(&tcx.cstore.crates_untracked()) }; - providers.crate_host_hash = |tcx, cnum| { - assert_ne!(cnum, LOCAL_CRATE); - tcx.cstore.crate_host_hash_untracked(cnum) - }; - providers.postorder_cnums = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.arena.alloc_slice(&tcx.cstore.postorder_cnums_untracked()) - }; providers.output_filenames = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); tcx.output_filenames.clone() @@ -3045,4 +3038,9 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { assert_eq!(cnum, LOCAL_CRATE); attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins) }; + providers.has_panic_handler = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + // We want to check if the panic handler was defined in this crate + tcx.lang_items().panic_impl().map_or(false, |did| did.is_local()) + }; } diff --git a/src/librustc/ty/diagnostics.rs b/src/librustc/ty/diagnostics.rs new file mode 100644 index 0000000000..3a55aefe85 --- /dev/null +++ b/src/librustc/ty/diagnostics.rs @@ -0,0 +1,56 @@ +//! Diagnostics related methods for `TyS`. + +use crate::ty::TyS; +use crate::ty::TyKind::*; +use crate::ty::sty::InferTy; + +impl<'tcx> TyS<'tcx> { + /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. + pub fn is_primitive_ty(&self) -> bool { + match self.kind { + Bool | Char | Str | Int(_) | Uint(_) | Float(_) | + Infer(InferTy::IntVar(_)) | Infer(InferTy::FloatVar(_)) | + Infer(InferTy::FreshIntTy(_)) | Infer(InferTy::FreshFloatTy(_)) => true, + _ => false, + } + } + + /// Whether the type is succinctly representable as a type instead of just referred to with a + /// description in error messages. This is used in the main error message. + pub fn is_simple_ty(&self) -> bool { + match self.kind { + Bool | Char | Str | Int(_) | Uint(_) | Float(_) | + Infer(InferTy::IntVar(_)) | Infer(InferTy::FloatVar(_)) | + Infer(InferTy::FreshIntTy(_)) | Infer(InferTy::FreshFloatTy(_)) => true, + Ref(_, x, _) | Array(x, _) | Slice(x) => x.peel_refs().is_simple_ty(), + Tuple(tys) if tys.is_empty() => true, + _ => false, + } + } + + /// Whether the type is succinctly representable as a type instead of just referred to with a + /// description in error messages. This is used in the primary span label. Beyond what + /// `is_simple_ty` includes, it also accepts ADTs with no type arguments and references to + /// ADTs with no type arguments. + pub fn is_simple_text(&self) -> bool { + match self.kind { + Adt(_, substs) => substs.types().next().is_none(), + Ref(_, ty, _) => ty.is_simple_text(), + _ => self.is_simple_ty(), + } + } + + /// Whether the type can be safely suggested during error recovery. + pub fn is_suggestable(&self) -> bool { + match self.kind { + Opaque(..) | + FnDef(..) | + FnPtr(..) | + Dynamic(..) | + Closure(..) | + Infer(..) | + Projection(..) => false, + _ => true, + } + } +} diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 77613b548c..be6d21564a 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -1,23 +1,24 @@ +use crate::hir; use crate::hir::def_id::DefId; use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt}; -use std::borrow::Cow; -use std::fmt; + +use errors::{Applicability, DiagnosticBuilder}; use rustc_target::spec::abi; use syntax::ast; -use syntax::errors::pluralise; -use errors::{Applicability, DiagnosticBuilder}; +use syntax::errors::pluralize; use syntax_pos::Span; -use crate::hir; +use std::borrow::Cow; +use std::fmt; -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)] pub struct ExpectedFound { pub expected: T, pub found: T, } // Data structures used in type unification -#[derive(Clone, Debug)] +#[derive(Clone, Debug, TypeFoldable)] pub enum TypeError<'tcx> { Mismatch, UnsafetyMismatch(ExpectedFound), @@ -64,8 +65,11 @@ pub enum UnconstrainedNumeric { impl<'tcx> fmt::Display for TypeError<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use self::TypeError::*; - fn report_maybe_different(f: &mut fmt::Formatter<'_>, - expected: &str, found: &str) -> fmt::Result { + fn report_maybe_different( + f: &mut fmt::Formatter<'_>, + expected: &str, + found: &str, + ) -> fmt::Result { // A naive approach to making sure that we're not reporting silly errors such as: // (expected closure, found closure). if expected == found { @@ -100,17 +104,17 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { write!(f, "expected a tuple with {} element{}, \ found one with {} element{}", values.expected, - pluralise!(values.expected), + pluralize!(values.expected), values.found, - pluralise!(values.found)) + pluralize!(values.found)) } FixedArraySize(values) => { write!(f, "expected an array with a fixed size of {} element{}, \ found one with {} element{}", values.expected, - pluralise!(values.expected), + pluralize!(values.expected), values.found, - pluralise!(values.found)) + pluralize!(values.found)) } ArgCount => { write!(f, "incorrect number of function parameters") @@ -165,7 +169,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ProjectionBoundsLength(ref values) => { write!(f, "expected {} associated type binding{}, found {}", values.expected, - pluralise!(values.expected), + pluralize!(values.expected), values.found) }, ExistentialMismatch(ref values) => { @@ -183,46 +187,77 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { } } +impl<'tcx> TypeError<'tcx> { + pub fn must_include_note(&self) -> bool { + use self::TypeError::*; + match self { + CyclicTy(_) | + UnsafetyMismatch(_) | + Mismatch | + AbiMismatch(_) | + FixedArraySize(_) | + Sorts(_) | + IntMismatch(_) | + FloatMismatch(_) | + VariadicMismatch(_) => false, + + Mutability | + TupleSize(_) | + ArgCount | + RegionsDoesNotOutlive(..) | + RegionsInsufficientlyPolymorphic(..) | + RegionsOverlyPolymorphic(..) | + RegionsPlaceholderMismatch | + Traits(_) | + ProjectionMismatched(_) | + ProjectionBoundsLength(_) | + ExistentialMismatch(_) | + ConstMismatch(_) | + IntrinsicCast | + ObjectUnsafeCoercion(_) => true, + } + } +} + impl<'tcx> ty::TyS<'tcx> { pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> { match self.kind { ty::Bool | ty::Char | ty::Int(_) | - ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string().into(), - ty::Tuple(ref tys) if tys.is_empty() => self.to_string().into(), + ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => format!("`{}`", self).into(), + ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(), ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(), ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(), - ty::Array(_, n) => { + ty::Array(t, n) => { let n = tcx.lift(&n).unwrap(); match n.try_eval_usize(tcx, ty::ParamEnv::empty()) { - Some(n) => { - format!("array of {} element{}", n, pluralise!(n)).into() - } + _ if t.is_simple_ty() => format!("array `{}`", self).into(), + Some(n) => format!("array of {} element{} ", n, pluralize!(n)).into(), None => "array".into(), } } + ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(), ty::Slice(_) => "slice".into(), ty::RawPtr(_) => "*-ptr".into(), - ty::Ref(region, ty, mutbl) => { + ty::Ref(_, ty, mutbl) => { let tymut = ty::TypeAndMut { ty, mutbl }; let tymut_string = tymut.to_string(); - if tymut_string == "_" || //unknown type name, - tymut_string.len() > 10 || //name longer than saying "reference", - region.to_string() != "'_" //... or a complex type - { - format!("{}reference", match mutbl { - hir::Mutability::MutMutable => "mutable ", - _ => "" - }).into() - } else { - format!("&{}", tymut_string).into() + if tymut_string != "_" && ( + ty.is_simple_text() || tymut_string.len() < "mutable reference".len() + ) { + format!("`&{}`", tymut_string).into() + } else { // Unknown type name, it's long or has type arguments + match mutbl { + hir::Mutability::Mutable => "mutable reference", + _ => "reference", + }.into() } } ty::FnDef(..) => "fn item".into(), ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(ref inner, ..) => { if let Some(principal) = inner.principal() { - format!("trait {}", tcx.def_path_str(principal.def_id())).into() + format!("trait `{}`", tcx.def_path_str(principal.def_id())).into() } else { "trait".into() } @@ -241,11 +276,41 @@ impl<'tcx> ty::TyS<'tcx> { ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), ty::Projection(_) => "associated type".into(), ty::UnnormalizedProjection(_) => "non-normalized associated type".into(), - ty::Param(_) => "type parameter".into(), + ty::Param(p) => format!("type parameter `{}`", p).into(), ty::Opaque(..) => "opaque type".into(), ty::Error => "type error".into(), } } + + pub fn prefix_string(&self) -> Cow<'static, str> { + match self.kind { + ty::Infer(_) | ty::Error | ty::Bool | ty::Char | ty::Int(_) | + ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => "type".into(), + ty::Tuple(ref tys) if tys.is_empty() => "unit type".into(), + ty::Adt(def, _) => def.descr().into(), + ty::Foreign(_) => "extern type".into(), + ty::Array(..) => "array".into(), + ty::Slice(_) => "slice".into(), + ty::RawPtr(_) => "raw pointer".into(), + ty::Ref(.., mutbl) => match mutbl { + hir::Mutability::Mutable => "mutable reference", + _ => "reference" + }.into(), + ty::FnDef(..) => "fn item".into(), + ty::FnPtr(_) => "fn pointer".into(), + ty::Dynamic(..) => "trait object".into(), + ty::Closure(..) => "closure".into(), + ty::Generator(..) => "generator".into(), + ty::GeneratorWitness(..) => "generator witness".into(), + ty::Tuple(..) => "tuple".into(), + ty::Placeholder(..) => "higher-ranked type".into(), + ty::Bound(..) => "bound type variable".into(), + ty::Projection(_) => "associated type".into(), + ty::UnnormalizedProjection(_) => "associated type".into(), + ty::Param(_) => "type parameter".into(), + ty::Opaque(..) => "opaque type".into(), + } + } } impl<'tcx> TyCtxt<'tcx> { @@ -254,6 +319,7 @@ impl<'tcx> TyCtxt<'tcx> { db: &mut DiagnosticBuilder<'_>, err: &TypeError<'tcx>, sp: Span, + body_owner_def_id: DefId, ) { use self::TypeError::*; @@ -288,7 +354,16 @@ impl<'tcx> TyCtxt<'tcx> { ); } }, - (ty::Param(_), ty::Param(_)) => { + (ty::Param(expected), ty::Param(found)) => { + let generics = self.generics_of(body_owner_def_id); + let e_span = self.def_span(generics.type_param(expected, self).def_id); + if !sp.contains(e_span) { + db.span_label(e_span, "expected type parameter"); + } + let f_span = self.def_span(generics.type_param(found, self).def_id); + if !sp.contains(f_span) { + db.span_label(f_span, "found type parameter"); + } db.note("a type parameter was expected, but a different one was found; \ you might be missing a type parameter or trait bound"); db.note("for more information, visit \ @@ -301,7 +376,12 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Param(_), ty::Projection(_)) | (ty::Projection(_), ty::Param(_)) => { db.note("you might be missing a type parameter or trait bound"); } - (ty::Param(_), _) | (_, ty::Param(_)) => { + (ty::Param(p), _) | (_, ty::Param(p)) => { + let generics = self.generics_of(body_owner_def_id); + let p_span = self.def_span(generics.type_param(p, self).def_id); + if !sp.contains(p_span) { + db.span_label(p_span, "this type parameter"); + } db.help("type parameters must be constrained to match other types"); if self.sess.teach(&db.get_code().unwrap()) { db.help("given a type parameter `T` and a method `foo`: diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index d4b7f37b12..aee0ec7806 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -1,6 +1,5 @@ use crate::ty::subst::{SubstsRef, GenericArgKind}; use crate::ty::{self, Ty, TypeFlags, InferConst}; -use crate::mir::interpret::ConstValue; #[derive(Debug)] pub struct FlagComputation { @@ -232,29 +231,27 @@ impl FlagComputation { fn add_const(&mut self, c: &ty::Const<'_>) { self.add_ty(c.ty); match c.val { - ConstValue::Unevaluated(_, substs) => { + ty::ConstKind::Unevaluated(_, substs) => { self.add_substs(substs); self.add_flags(TypeFlags::HAS_PROJECTION); }, - ConstValue::Infer(infer) => { + ty::ConstKind::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER); match infer { InferConst::Fresh(_) => {} InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX), } } - ConstValue::Bound(debruijn, _) => self.add_binder(debruijn), - ConstValue::Param(_) => { + ty::ConstKind::Bound(debruijn, _) => self.add_binder(debruijn), + ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_flags(TypeFlags::HAS_PARAMS); } - ConstValue::Placeholder(_) => { + ty::ConstKind::Placeholder(_) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); } - ConstValue::Scalar(_) => {} - ConstValue::Slice { .. } => {} - ConstValue::ByRef { .. } => {} + ty::ConstKind::Value(_) => {} } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index bacf3d42f0..8b78b0f335 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -32,7 +32,6 @@ //! looking for, and does not need to visit anything else. use crate::hir::def_id::DefId; -use crate::mir::interpret::ConstValue; use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags, flags::FlagComputation}; use std::collections::BTreeMap; @@ -42,8 +41,7 @@ use crate::util::nodemap::FxHashSet; /// This trait is implemented for every type that can be folded. /// Basically, every type that has a corresponding method in `TypeFolder`. /// -/// To implement this conveniently, use the -/// `BraceStructTypeFoldableImpl` etc macros found in `macros.rs`. +/// To implement this conveniently, use the derive macro located in librustc_macros. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn super_fold_with>(&self, folder: &mut F) -> Self; fn fold_with>(&self, folder: &mut F) -> Self { @@ -521,7 +519,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ConstValue::Bound(debruijn, bound_const), ty } = *ct { + if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } = *ct { if debruijn == self.current_index { let fld_c = &mut self.fld_c; let ct = fld_c(bound_const, ty); @@ -568,7 +566,7 @@ impl<'tcx> TyCtxt<'tcx> { let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty)); let fld_c = |bound_ct, ty| { self.mk_const(ty::Const { - val: ConstValue::Bound(ty::INNERMOST, bound_ct), + val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty, }) }; @@ -801,7 +799,7 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ConstValue::Bound(debruijn, bound_ct), ty } = *ct { + if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct { if self.amount == 0 || debruijn < self.current_index { ct } else { @@ -813,7 +811,7 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { } }; self.tcx.mk_const(ty::Const { - val: ConstValue::Bound(debruijn, bound_ct), + val: ty::ConstKind::Bound(debruijn, bound_ct), ty, }) } @@ -919,7 +917,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { // const, as it has types/regions embedded in a lot of other // places. match ct.val { - ConstValue::Bound(debruijn, _) if debruijn >= self.outer_index => true, + ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => true, _ => ct.super_visit_with(self), } } diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 63cc60d80a..227fbf967c 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -76,19 +76,19 @@ impl<'tcx> DefIdForest { break; } - for id in ret.root_ids.drain() { + for id in ret.root_ids.drain(..) { if next_forest.contains(tcx, id) { next_ret.push(id); } else { old_ret.push(id); } } - ret.root_ids.extend(old_ret.drain()); + ret.root_ids.extend(old_ret.drain(..)); next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id))); mem::swap(&mut next_ret, &mut ret.root_ids); - next_ret.drain(); + next_ret.drain(..); } ret } @@ -101,7 +101,7 @@ impl<'tcx> DefIdForest { let mut ret = DefIdForest::empty(); let mut next_ret = SmallVec::new(); for next_forest in iter { - next_ret.extend(ret.root_ids.drain().filter(|&id| !next_forest.contains(tcx, id))); + next_ret.extend(ret.root_ids.drain(..).filter(|&id| !next_forest.contains(tcx, id))); for id in next_forest.root_ids { if !next_ret.contains(&id) { @@ -110,7 +110,7 @@ impl<'tcx> DefIdForest { } mem::swap(&mut next_ret, &mut ret.root_ids); - next_ret.drain(); + next_ret.drain(..); } ret } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 5139c8085a..366951bc9f 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,8 +1,7 @@ use crate::hir::CodegenFnAttrFlags; -use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; -use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt}; +use crate::ty::{self, Ty, TypeFoldable, SubstsRef, TyCtxt}; use crate::ty::print::{FmtPrinter, Printer}; use crate::traits; use crate::middle::lang_items::DropInPlaceFnLangItem; @@ -10,9 +9,9 @@ use rustc_target::spec::abi::Abi; use rustc_macros::HashStable; use std::fmt; -use std::iter; -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable, Lift)] pub struct Instance<'tcx> { pub def: InstanceDef<'tcx>, pub substs: SubstsRef<'tcx>, @@ -28,17 +27,26 @@ pub enum InstanceDef<'tcx> { /// `fn()` pointer where the function itself cannot be turned into a pointer. /// - /// One example in the compiler today is functions annotated with `#[track_caller]`, which - /// must have their implicit caller location argument populated for a call. Because this is a - /// required part of the function's ABI but can't be tracked as a property of the function - /// pointer, we create a single "caller location" at the site where the function is reified. + /// One example is `::fn`, where the shim contains + /// a virtual call, which codegen supports only via a direct call to the + /// `::fn` instance (an `InstanceDef::Virtual`). + /// + /// Another example is functions annotated with `#[track_caller]`, which + /// must have their implicit caller location argument populated for a call. + /// Because this is a required part of the function's ABI but can't be tracked + /// as a property of the function pointer, we use a single "caller location" + /// (the definition of the function itself). ReifyShim(DefId), /// `::call_*` - /// `DefId` is `FnTrait::call_*` + /// `DefId` is `FnTrait::call_*`. FnPtrShim(DefId, Ty<'tcx>), - /// `::fn` + /// `::fn`, "direct calls" of which are implicitly + /// codegen'd as virtual calls. + /// + /// NB: if this is reified to a `fn` pointer, a `ReifyShim` is used + /// (see `ReifyShim` above for more details on that). Virtual(DefId, usize), /// `<[mut closure] as FnOnce>::call_once` @@ -60,70 +68,6 @@ impl<'tcx> Instance<'tcx> { &ty, ) } - - fn fn_sig_noadjust(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { - let ty = self.ty(tcx); - match ty.kind { - ty::FnDef(..) | - // Shims currently have type FnPtr. Not sure this should remain. - ty::FnPtr(_) => ty.fn_sig(tcx), - ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(def_id, tcx); - - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.c_variadic, - sig.unsafety, - sig.abi - )) - } - ty::Generator(def_id, substs, _) => { - let sig = substs.as_generator().poly_sig(def_id, tcx); - - let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); - let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); - - let pin_did = tcx.lang_items().pin_type().unwrap(); - let pin_adt_ref = tcx.adt_def(pin_did); - let pin_substs = tcx.intern_substs(&[env_ty.into()]); - let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); - - sig.map_bound(|sig| { - let state_did = tcx.lang_items().gen_state().unwrap(); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.intern_substs(&[ - sig.yield_ty.into(), - sig.return_ty.into(), - ]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - - tcx.mk_fn_sig(iter::once(env_ty), - ret_ty, - false, - Unsafety::Normal, - Abi::Rust - ) - }) - } - _ => bug!("unexpected type {:?} in Instance::fn_sig_noadjust", ty) - } - } - - pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let mut fn_sig = self.fn_sig_noadjust(tcx); - if let InstanceDef::VtableShim(..) = self.def { - // Modify fn(self, ...) to fn(self: *mut Self, ...) - fn_sig = fn_sig.map_bound(|mut fn_sig| { - let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); - inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); - fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); - fn_sig - }); - } - fn_sig - } } impl<'tcx> InstanceDef<'tcx> { @@ -172,6 +116,10 @@ impl<'tcx> InstanceDef<'tcx> { } tcx.codegen_fn_attrs(self.def_id()).requests_inline() } + + pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { + tcx.codegen_fn_attrs(self.def_id()).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) + } } impl<'tcx> fmt::Display for Instance<'tcx> { @@ -195,7 +143,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { write!(f, " - intrinsic") } InstanceDef::Virtual(_, num) => { - write!(f, " - shim(#{})", num) + write!(f, " - virtual#{}", num) } InstanceDef::FnPtrShim(_, ty) => { write!(f, " - shim({:?})", ty) @@ -310,20 +258,20 @@ impl<'tcx> Instance<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); - Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| { - let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags - .contains(CodegenFnAttrFlags::TRACK_CALLER); - + Instance::resolve(tcx, param_env, def_id, substs).map(|mut resolved| { match resolved.def { - InstanceDef::Item(def_id) if has_track_caller(def_id) => { + InstanceDef::Item(def_id) if resolved.def.requires_caller_location(tcx) => { debug!(" => fn pointer created for function with #[track_caller]"); - Instance { - def: InstanceDef::ReifyShim(def_id), - substs, - } - }, - _ => resolved, + resolved.def = InstanceDef::ReifyShim(def_id); + } + InstanceDef::Virtual(def_id, _) => { + debug!(" => fn pointer created for virtual call"); + resolved.def = InstanceDef::ReifyShim(def_id); + } + _ => {} } + + resolved }) } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e82232ac10..c7278dc4fa 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -23,7 +23,7 @@ use rustc_index::vec::{IndexVec, Idx}; pub use rustc_target::abi::*; use rustc_target::spec::{HasTargetSpec, abi::Abi as SpecAbi}; use rustc_target::abi::call::{ - ArgAttribute, ArgAttributes, ArgType, Conv, FnType, PassMode, Reg, RegKind + ArgAttribute, ArgAttributes, ArgAbi, Conv, FnAbi, PassMode, Reg, RegKind }; pub trait IntegerExt { @@ -132,8 +132,8 @@ impl PrimitiveExt for Primitive { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { Int(i, signed) => i.to_ty(tcx, signed), - Float(FloatTy::F32) => tcx.types.f32, - Float(FloatTy::F64) => tcx.types.f64, + F32 => tcx.types.f32, + F64 => tcx.types.f64, Pointer => tcx.mk_mut_ptr(tcx.mk_unit()), } } @@ -144,7 +144,7 @@ impl PrimitiveExt for Primitive { match *self { Int(i, signed) => i.to_ty(tcx, signed), Pointer => tcx.types.usize, - Float(..) => bug!("floats do not have an int type"), + F32 | F64 => bug!("floats do not have an int type"), } } } @@ -538,7 +538,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ty::Uint(ity) => { scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity)), false)) } - ty::Float(fty) => scalar(Float(fty)), + ty::Float(fty) => scalar(match fty { + ast::FloatTy::F32 => F32, + ast::FloatTy::F64 => F64, + }), ty::FnPtr(_) => { let mut ptr = scalar_unit(Pointer); ptr.valid_range = 1..=*ptr.valid_range.end(); @@ -694,7 +697,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // SIMD vector types. ty::Adt(def, ..) if def.repr.simd() => { let element = self.layout_of(ty.simd_type(tcx))?; - let count = ty.simd_size(tcx) as u64; + let count = ty.simd_size(tcx); assert!(count > 0); let scalar = match element.abi { Abi::Scalar(ref scalar) => scalar.clone(), @@ -1611,13 +1614,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // (delay format until we actually need it) let record = |kind, packed, opt_discr_size, variants| { let type_desc = format!("{:?}", layout.ty); - self.tcx.sess.code_stats.borrow_mut().record_type_size(kind, - type_desc, - layout.align.abi, - layout.size, - packed, - opt_discr_size, - variants); + self.tcx.sess.code_stats.record_type_size(kind, + type_desc, + layout.align.abi, + layout.size, + packed, + opt_discr_size, + variants); }; let adt_def = match layout.ty.kind { @@ -2100,8 +2103,8 @@ where ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { assert!(i < this.fields.count()); - // Reuse the fat *T type as its own thin pointer data field. - // This provides information about e.g., DST struct pointees + // Reuse the fat `*T` type as its own thin pointer data field. + // This provides information about, e.g., DST struct pointees // (which may have no non-DST form), and will work as long // as the `Abi` or `FieldPlacement` is checked by users. if i == 0 { @@ -2218,12 +2221,12 @@ where let tcx = cx.tcx(); let is_freeze = ty.is_freeze(tcx, cx.param_env(), DUMMY_SP); let kind = match mt { - hir::MutImmutable => if is_freeze { + hir::Mutability::Immutable => if is_freeze { PointerKind::Frozen } else { PointerKind::Shared }, - hir::MutMutable => { + hir::Mutability::Mutable => { // Previously we would only emit noalias annotations for LLVM >= 6 or in // panic=abort mode. That was deemed right, as prior versions had many bugs // in conjunction with unwinding, but later versions didn’t seem to have @@ -2324,170 +2327,89 @@ where } } -impl<'a> HashStable> for Variants { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use crate::ty::layout::Variants::*; - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - Single { index } => { - index.hash_stable(hcx, hasher); - } - Multiple { - ref discr, - ref discr_kind, - discr_index, - ref variants, - } => { - discr.hash_stable(hcx, hasher); - discr_kind.hash_stable(hcx, hasher); - discr_index.hash_stable(hcx, hasher); - variants.hash_stable(hcx, hasher); - } - } - } -} - -impl<'a> HashStable> for DiscriminantKind { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use crate::ty::layout::DiscriminantKind::*; - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - Tag => {} - Niche { - dataful_variant, - ref niche_variants, - niche_start, - } => { - dataful_variant.hash_stable(hcx, hasher); - niche_variants.start().hash_stable(hcx, hasher); - niche_variants.end().hash_stable(hcx, hasher); - niche_start.hash_stable(hcx, hasher); - } - } - } -} - -impl<'a> HashStable> for FieldPlacement { +impl<'a, 'tcx> HashStable> for LayoutError<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use crate::ty::layout::FieldPlacement::*; + use crate::ty::layout::LayoutError::*; mem::discriminant(self).hash_stable(hcx, hasher); match *self { - Union(count) => { - count.hash_stable(hcx, hasher); - } - Array { count, stride } => { - count.hash_stable(hcx, hasher); - stride.hash_stable(hcx, hasher); - } - Arbitrary { ref offsets, ref memory_index } => { - offsets.hash_stable(hcx, hasher); - memory_index.hash_stable(hcx, hasher); - } + Unknown(t) | + SizeOverflow(t) => t.hash_stable(hcx, hasher) } } } -impl<'a> HashStable> for VariantIdx { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.as_u32().hash_stable(hcx, hasher) - } -} - -impl<'a> HashStable> for Abi { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use crate::ty::layout::Abi::*; - mem::discriminant(self).hash_stable(hcx, hasher); - match *self { - Uninhabited => {} - Scalar(ref value) => { - value.hash_stable(hcx, hasher); - } - ScalarPair(ref a, ref b) => { - a.hash_stable(hcx, hasher); - b.hash_stable(hcx, hasher); - } - Vector { ref element, count } => { - element.hash_stable(hcx, hasher); - count.hash_stable(hcx, hasher); - } - Aggregate { sized } => { - sized.hash_stable(hcx, hasher); +impl<'tcx> ty::Instance<'tcx> { + // NOTE(eddyb) this is private to avoid using it from outside of + // `FnAbi::of_instance` - any other uses are either too high-level + // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), + // or should go through `FnAbi` instead, to avoid losing any + // adjustments `FnAbi::of_instance` might be performing. + fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + let ty = self.ty(tcx); + match ty.kind { + ty::FnDef(..) | + // Shims currently have type FnPtr. Not sure this should remain. + ty::FnPtr(_) => { + let mut sig = ty.fn_sig(tcx); + if let ty::InstanceDef::VtableShim(..) = self.def { + // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. + sig = sig.map_bound(|mut sig| { + let mut inputs_and_output = sig.inputs_and_output.to_vec(); + inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); + sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + sig + }); + } + sig + } + ty::Closure(def_id, substs) => { + let sig = substs.as_closure().sig(def_id, tcx); + + let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); + sig.map_bound(|sig| tcx.mk_fn_sig( + iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.c_variadic, + sig.unsafety, + sig.abi + )) + } + ty::Generator(def_id, substs, _) => { + let sig = substs.as_generator().poly_sig(def_id, tcx); + + let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); + let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); + + let pin_did = tcx.lang_items().pin_type().unwrap(); + let pin_adt_ref = tcx.adt_def(pin_did); + let pin_substs = tcx.intern_substs(&[env_ty.into()]); + let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); + + sig.map_bound(|sig| { + let state_did = tcx.lang_items().gen_state().unwrap(); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[ + sig.yield_ty.into(), + sig.return_ty.into(), + ]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + + tcx.mk_fn_sig(iter::once(env_ty), + ret_ty, + false, + hir::Unsafety::Normal, + rustc_target::spec::abi::Abi::Rust + ) + }) } + _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) } } } -impl<'a> HashStable> for Scalar { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let Scalar { value, ref valid_range } = *self; - value.hash_stable(hcx, hasher); - valid_range.start().hash_stable(hcx, hasher); - valid_range.end().hash_stable(hcx, hasher); - } -} - -impl_stable_hash_for!(struct crate::ty::layout::Niche { - offset, - scalar -}); - -impl_stable_hash_for!(struct crate::ty::layout::LayoutDetails { - variants, - fields, - abi, - largest_niche, - size, - align -}); - -impl_stable_hash_for!(enum crate::ty::layout::Integer { - I8, - I16, - I32, - I64, - I128 -}); - -impl_stable_hash_for!(enum crate::ty::layout::Primitive { - Int(integer, signed), - Float(fty), - Pointer -}); - -impl_stable_hash_for!(struct crate::ty::layout::AbiAndPrefAlign { - abi, - pref -}); - -impl<'tcx> HashStable> for Align { - fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { - self.bytes().hash_stable(hcx, hasher); - } -} - -impl<'tcx> HashStable> for Size { - fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { - self.bytes().hash_stable(hcx, hasher); - } -} - -impl<'a, 'tcx> HashStable> for LayoutError<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use crate::ty::layout::LayoutError::*; - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - Unknown(t) | - SizeOverflow(t) => t.hash_stable(hcx, hasher) - } - } -} - -pub trait FnTypeExt<'tcx, C> +pub trait FnAbiExt<'tcx, C> where C: LayoutOf, TyLayout = TyLayout<'tcx>> + HasDataLayout @@ -2495,19 +2417,30 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self; - fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` + /// instead, where the instance is a `InstanceDef::Virtual`. + fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to a `InstanceDef::Virtual` instance (of `::fn`). + fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; + fn new_internal( cx: &C, - sig: ty::FnSig<'tcx>, + sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], - mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgType<'tcx, Ty<'tcx>>, + caller_location: Option>, + mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgAbi<'tcx, Ty<'tcx>>, ) -> Self; fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); } -impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> +impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> where C: LayoutOf, TyLayout = TyLayout<'tcx>> + HasDataLayout @@ -2515,25 +2448,25 @@ where + HasTyCtxt<'tcx> + HasParamEnv<'tcx>, { - fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self { - let sig = instance.fn_sig(cx.tcx()); - let sig = cx - .tcx() - .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - call::FnType::new(cx, sig, &[]) + fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { + call::FnAbi::new_internal(cx, sig, extra_args, None, |ty, _| ArgAbi::new(cx.layout_of(ty))) } - fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - call::FnType::new_internal(cx, sig, extra_args, |ty, _| ArgType::new(cx.layout_of(ty))) - } + fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { + let sig = instance.fn_sig_for_fn_abi(cx.tcx()); - fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - FnTypeExt::new_internal(cx, sig, extra_args, |ty, arg_idx| { + let caller_location = if instance.def.requires_caller_location(cx.tcx()) { + Some(cx.tcx().caller_location_ty()) + } else { + None + }; + + call::FnAbi::new_internal(cx, sig, extra_args, caller_location, |ty, arg_idx| { let mut layout = cx.layout_of(ty); // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait` // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen - if arg_idx == Some(0) { + if let (ty::InstanceDef::Virtual(..), Some(0)) = (&instance.def, arg_idx) { let fat_pointer_ty = if layout.is_unsized() { // unsized `self` is passed as a pointer to `self` // FIXME (mikeyhew) change this to use &own if it is ever added to the language @@ -2553,7 +2486,7 @@ where 'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr() && !fat_pointer_layout.ty.is_region_ptr() { - 'iter_fields: for i in 0..fat_pointer_layout.fields.count() { + for i in 0..fat_pointer_layout.fields.count() { let field_layout = fat_pointer_layout.field(cx, i); if !field_layout.is_zst() { @@ -2578,21 +2511,26 @@ where layout = cx.layout_of(unit_pointer_ty); layout.ty = fat_pointer_ty; } - ArgType::new(layout) + ArgAbi::new(layout) }) } fn new_internal( cx: &C, - sig: ty::FnSig<'tcx>, + sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], - mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgType<'tcx, Ty<'tcx>>, + caller_location: Option>, + mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgAbi<'tcx, Ty<'tcx>>, ) -> Self { - debug!("FnType::new_internal({:?}, {:?})", sig, extra_args); + debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); + + let sig = cx + .tcx() + .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); use rustc_target::spec::abi::Abi::*; let conv = match cx.tcx().sess.target.target.adjust_abi(sig.abi) { - RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::C, + RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust, // It's the ABI's job to select this, not ours. System => bug!("system abi should be selected elsewhere"), @@ -2674,9 +2612,16 @@ where if let Some(pointee) = layout.pointee_info_at(cx, offset) { if let Some(kind) = pointee.safe { - attrs.pointee_size = pointee.size; attrs.pointee_align = Some(pointee.align); + // `Box` (`UniqueBorrowed`) are not necessarily dereferencable + // for the entire duration of the function as they can be deallocated + // any time. Set their valid size to 0. + attrs.pointee_size = match kind { + PointerKind::UniqueOwned => Size::ZERO, + _ => pointee.size + }; + // `Box` pointer parameters never alias because ownership is transferred // `&mut` pointer parameters never alias other parameters, // or mutable global data @@ -2741,20 +2686,21 @@ where arg }; - let mut fn_ty = FnType { + let mut fn_abi = FnAbi { ret: arg_of(sig.output(), None), args: inputs .iter() .cloned() .chain(extra_args) + .chain(caller_location) .enumerate() .map(|(i, ty)| arg_of(ty, Some(i))) .collect(), c_variadic: sig.c_variadic, conv, }; - fn_ty.adjust_for_abi(cx, sig.abi); - fn_ty + fn_abi.adjust_for_abi(cx, sig.abi); + fn_abi } fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) { @@ -2767,7 +2713,7 @@ where || abi == SpecAbi::RustIntrinsic || abi == SpecAbi::PlatformIntrinsic { - let fixup = |arg: &mut ArgType<'tcx, Ty<'tcx>>| { + let fixup = |arg: &mut ArgAbi<'tcx, Ty<'tcx>>| { if arg.is_ignore() { return; } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 60028f2488..78a31f4e54 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -18,7 +18,7 @@ use crate::infer::canonical::Canonical; use crate::middle::cstore::CrateStoreDyn; use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::resolve_lifetime::ObjectLifetimeDefault; -use crate::mir::Body; +use crate::mir::ReadOnlyBodyAndCache; use crate::mir::interpret::{GlobalId, ErrorHandled}; use crate::mir::GeneratorLayout; use crate::session::CrateDisambiguator; @@ -63,7 +63,7 @@ pub use self::sty::{InferTy, ParamTy, ParamConst, InferConst, ProjectionTy, Exis pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; pub use self::sty::{TraitRef, TyKind, PolyTraitRef}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; -pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const}; +pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, ConstKind}; pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; pub use self::sty::RegionKind; pub use self::sty::{TyVid, IntVid, FloatVid, ConstVid, RegionVid}; @@ -71,6 +71,7 @@ pub use self::sty::BoundRegion::*; pub use self::sty::InferTy::*; pub use self::sty::RegionKind::*; pub use self::sty::TyKind::*; +pub use crate::ty::diagnostics::*; pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; @@ -122,6 +123,7 @@ mod instance; mod structural_impls; mod structural_match; mod sty; +mod diagnostics; // Data types @@ -166,7 +168,7 @@ impl AssocItemContainer { /// The "header" of an impl is everything outside the body: a Self type, a trait /// ref (in the case of a trait impl), and a set of predicates (from the /// bounds / where-clauses). -#[derive(Clone, Debug)] +#[derive(Clone, Debug, TypeFoldable)] pub struct ImplHeader<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, @@ -552,37 +554,6 @@ impl<'tcx> Hash for TyS<'tcx> { } } -impl<'tcx> TyS<'tcx> { - pub fn is_primitive_ty(&self) -> bool { - match self.kind { - Bool | - Char | - Int(_) | - Uint(_) | - Float(_) | - Infer(InferTy::IntVar(_)) | - Infer(InferTy::FloatVar(_)) | - Infer(InferTy::FreshIntTy(_)) | - Infer(InferTy::FreshFloatTy(_)) => true, - Ref(_, x, _) => x.is_primitive_ty(), - _ => false, - } - } - - pub fn is_suggestable(&self) -> bool { - match self.kind { - Opaque(..) | - FnDef(..) | - FnPtr(..) | - Dynamic(..) | - Closure(..) | - Infer(..) | - Projection(..) => false, - _ => true, - } - } -} - impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let ty::TyS { @@ -832,7 +803,7 @@ pub struct UpvarBorrow<'tcx> { pub type UpvarListMap = FxHashMap>; pub type UpvarCaptureMap<'tcx> = FxHashMap>; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, TypeFoldable)] pub struct ClosureUpvar<'tcx> { pub res: Res, pub span: Span, @@ -1097,7 +1068,8 @@ impl<'tcx> GenericPredicates<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub enum Predicate<'tcx> { /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -1247,7 +1219,8 @@ impl<'tcx> Predicate<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx> } @@ -1275,8 +1248,8 @@ impl<'tcx> PolyTraitPredicate<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, - Hash, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct OutlivesPredicate(pub A, pub B); // `A: B` pub type PolyOutlivesPredicate = ty::Binder>; pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; @@ -1284,7 +1257,8 @@ pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'t pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder>; pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder>; -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct SubtypePredicate<'tcx> { pub a_is_expected: bool, pub a: Ty<'tcx>, @@ -1304,7 +1278,8 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder>; /// equality between arbitrary types. Processing an instance of /// Form #2 eventually yields one of these `ProjectionPredicate` /// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct ProjectionPredicate<'tcx> { pub projection_ty: ProjectionTy<'tcx>, pub ty: Ty<'tcx>, @@ -1534,7 +1509,7 @@ impl<'tcx> Predicate<'tcx> { /// `[[], [U:Bar]]`. Now if there were some particular reference /// like `Foo`, then the `InstantiatedPredicates` would be `[[], /// [usize:Bar]]`. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, TypeFoldable)] pub struct InstantiatedPredicates<'tcx> { pub predicates: Vec>, } @@ -1586,12 +1561,11 @@ rustc_index::newtype_index! { /// type -- an idealized representative of "types in general" that we /// use for checking generic functions. pub struct UniverseIndex { + derive [HashStable] DEBUG_FORMAT = "U{}", } } -impl_stable_hash_for!(struct UniverseIndex { private }); - impl UniverseIndex { pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0); @@ -1658,7 +1632,7 @@ pub type PlaceholderConst = Placeholder; /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this /// particular point. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TypeFoldable)] pub struct ParamEnv<'tcx> { /// `Obligation`s that the caller must satisfy. This is basically /// the set of bounds on the in-scope type parameters, translated @@ -1764,7 +1738,7 @@ impl<'tcx> ParamEnv<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, pub value: T, @@ -1835,7 +1809,7 @@ bitflags! { } /// Definition of a variant -- a struct's fields or a enum variant. -#[derive(Debug)] +#[derive(Debug, HashStable)] pub struct VariantDef { /// `DefId` that identifies the variant itself. /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. @@ -1844,6 +1818,7 @@ pub struct VariantDef { /// If this variant is a struct variant, then this is `None`. pub ctor_def_id: Option, /// Variant or struct name. + #[stable_hasher(project(name))] pub ident: Ident, /// Discriminant of this variant. pub discr: VariantDiscr, @@ -1923,17 +1898,6 @@ impl<'tcx> VariantDef { } } -impl_stable_hash_for!(struct VariantDef { - def_id, - ctor_def_id, - ident -> (ident.name), - discr, - fields, - ctor_kind, - flags, - recovered -}); - #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] pub enum VariantDiscr { /// Explicit value for this variant, i.e., `X = 123`. @@ -1959,17 +1923,17 @@ pub struct FieldDef { /// /// These are all interned (by `intern_adt_def`) into the `adt_defs` table. /// -/// The initialism *"Adt"* stands for an [*algebraic data type (ADT)*][adt]. +/// The initialism *ADT* stands for an [*algebraic data type (ADT)*][adt]. /// This is slightly wrong because `union`s are not ADTs. /// Moreover, Rust only allows recursive data types through indirection. /// /// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type pub struct AdtDef { - /// `DefId` of the struct, enum or union item. + /// The `DefId` of the struct, enum or union item. pub did: DefId, /// Variants of the ADT. If this is a struct or union, then there will be a single variant. pub variants: IndexVec, - /// Flags of the ADT (e.g. is this a struct? is this non-exhaustive?) + /// Flags of the ADT (e.g., is this a struct? is this non-exhaustive?). flags: AdtFlags, /// Repr options provided by the user. pub repr: ReprOptions, @@ -1990,7 +1954,7 @@ impl Ord for AdtDef { } impl PartialEq for AdtDef { - // AdtDef are always interned and this is part of TyS equality + // `AdtDef`s are always interned, and this is part of `TyS` equality. #[inline] fn eq(&self, other: &Self) -> bool { ptr::eq(self, other) } } @@ -2012,7 +1976,6 @@ impl<'tcx> rustc_serialize::UseSpecializedEncodable for &'tcx AdtDef { impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx AdtDef {} - impl<'a> HashStable> for AdtDef { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { thread_local! { @@ -2057,7 +2020,7 @@ impl Into for AdtKind { } bitflags! { - #[derive(RustcEncodable, RustcDecodable, Default)] + #[derive(RustcEncodable, RustcDecodable, Default, HashStable)] pub struct ReprFlags: u8 { const IS_C = 1 << 0; const IS_SIMD = 1 << 1; @@ -2072,12 +2035,9 @@ bitflags! { } } -impl_stable_hash_for!(struct ReprFlags { - bits -}); - /// Represents the repr options provided by the user, -#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, + Default, HashStable)] pub struct ReprOptions { pub int: Option, pub align: Option, @@ -2085,13 +2045,6 @@ pub struct ReprOptions { pub flags: ReprFlags, } -impl_stable_hash_for!(struct ReprOptions { - align, - pack, - int, - flags -}); - impl ReprOptions { pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { let mut flags = ReprFlags::empty(); @@ -2693,8 +2646,8 @@ impl<'tcx> TyS<'tcx> { impl BorrowKind { pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { match m { - hir::MutMutable => MutBorrow, - hir::MutImmutable => ImmBorrow, + hir::Mutability::Mutable => MutBorrow, + hir::Mutability::Immutable => ImmBorrow, } } @@ -2704,13 +2657,13 @@ impl BorrowKind { /// question. pub fn to_mutbl_lossy(self) -> hir::Mutability { match self { - MutBorrow => hir::MutMutable, - ImmBorrow => hir::MutImmutable, + MutBorrow => hir::Mutability::Mutable, + ImmBorrow => hir::Mutability::Immutable, // We have no type corresponding to a unique imm borrow, so // use `&mut`. It gives all the capabilities of an `&uniq` // and hence is a safe "over approximation". - UniqueImmBorrow => hir::MutMutable, + UniqueImmBorrow => hir::Mutability::Mutable, } } @@ -2831,11 +2784,7 @@ impl<'tcx> TyCtxt<'tcx> { } }; - if is_associated_item { - Some(self.associated_item(def_id)) - } else { - None - } + is_associated_item.then(|| self.associated_item(def_id)) } fn associated_item_from_trait_item_ref(self, @@ -3032,10 +2981,10 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. - pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { + pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> ReadOnlyBodyAndCache<'tcx, 'tcx> { match instance { ty::InstanceDef::Item(did) => { - self.optimized_mir(did) + self.optimized_mir(did).unwrap_read_only() } ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) | @@ -3045,7 +2994,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) => { - self.mir_shims(instance) + self.mir_shims(instance).unwrap_read_only() } } } @@ -3300,7 +3249,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ParamEnv<'_> { let unnormalized_env = ty::ParamEnv::new( tcx.intern_predicates(&predicates), traits::Reveal::UserFacing, - if tcx.sess.opts.debugging_opts.chalk { Some(def_id) } else { None } + tcx.sess.opts.debugging_opts.chalk.then_some(def_id), ); let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| { @@ -3407,7 +3356,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { layout::provide(providers); util::provide(providers); constness::provide(providers); - crate::traits::query::dropck_outlives::provide(providers); *providers = ty::query::Providers { asyncness, associated_item, @@ -3436,17 +3384,13 @@ pub struct CrateInherentImpls { pub inherent_impls: DefIdMap>, } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] pub struct SymbolName { // FIXME: we don't rely on interning or equality here - better have // this be a `&'tcx str`. pub name: Symbol } -impl_stable_hash_for!(struct self::SymbolName { - name -}); - impl SymbolName { pub fn new(name: &str) -> SymbolName { SymbolName { diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index e72916de6a..7eb774849b 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -6,13 +6,11 @@ //! FIXME(eddyb) implement a custom `PrettyPrinter` for this. use rustc::hir::def_id::DefId; -use rustc::mir::interpret::ConstValue; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Const, Instance, Ty, TyCtxt}; use rustc::{bug, hir}; use std::fmt::Write; use std::iter; -use syntax::ast; /// Same as `unique_type_name()` but with the result pushed onto the given /// `output` parameter. @@ -39,20 +37,9 @@ impl DefPathBasedNames<'tcx> { ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), ty::Never => output.push_str("!"), - ty::Int(ast::IntTy::Isize) => output.push_str("isize"), - ty::Int(ast::IntTy::I8) => output.push_str("i8"), - ty::Int(ast::IntTy::I16) => output.push_str("i16"), - ty::Int(ast::IntTy::I32) => output.push_str("i32"), - ty::Int(ast::IntTy::I64) => output.push_str("i64"), - ty::Int(ast::IntTy::I128) => output.push_str("i128"), - ty::Uint(ast::UintTy::Usize) => output.push_str("usize"), - ty::Uint(ast::UintTy::U8) => output.push_str("u8"), - ty::Uint(ast::UintTy::U16) => output.push_str("u16"), - ty::Uint(ast::UintTy::U32) => output.push_str("u32"), - ty::Uint(ast::UintTy::U64) => output.push_str("u64"), - ty::Uint(ast::UintTy::U128) => output.push_str("u128"), - ty::Float(ast::FloatTy::F32) => output.push_str("f32"), - ty::Float(ast::FloatTy::F64) => output.push_str("f64"), + ty::Int(ty) => output.push_str(ty.name_str()), + ty::Uint(ty) => output.push_str(ty.name_str()), + ty::Float(ty) => output.push_str(ty.name_str()), ty::Adt(adt_def, substs) => { self.push_def_path(adt_def.did, output); self.push_generic_params(substs, iter::empty(), output, debug); @@ -72,17 +59,15 @@ impl DefPathBasedNames<'tcx> { ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { output.push('*'); match mutbl { - hir::MutImmutable => output.push_str("const "), - hir::MutMutable => output.push_str("mut "), + hir::Mutability::Immutable => output.push_str("const "), + hir::Mutability::Mutable => output.push_str("mut "), } self.push_type_name(inner_type, output, debug); } ty::Ref(_, inner_type, mutbl) => { output.push('&'); - if mutbl == hir::MutMutable { - output.push_str("mut "); - } + output.push_str(mutbl.prefix_str()); self.push_type_name(inner_type, output, debug); } @@ -114,9 +99,7 @@ impl DefPathBasedNames<'tcx> { ty::Foreign(did) => self.push_def_path(did, output), ty::FnDef(..) | ty::FnPtr(_) => { let sig = t.fn_sig(self.tcx); - if sig.unsafety() == hir::Unsafety::Unsafe { - output.push_str("unsafe "); - } + output.push_str(sig.unsafety().prefix_str()); let abi = sig.abi(); if abi != ::rustc_target::spec::abi::Abi::Rust { @@ -186,21 +169,16 @@ impl DefPathBasedNames<'tcx> { // If `debug` is true, usually-unprintable consts (such as `Infer`) will be printed, // as well as the unprintable types of constants (see `push_type_name` for more details). pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) { - match c.val { - ConstValue::Scalar(..) | ConstValue::Slice { .. } | ConstValue::ByRef { .. } => { - // FIXME(const_generics): we could probably do a better job here. - write!(output, "{:?}", c).unwrap() - } - _ => { - if debug { - write!(output, "{:?}", c).unwrap() - } else { - bug!( - "DefPathBasedNames: trying to create const name for unexpected const: {:?}", - c, - ); - } - } + if let ty::ConstKind::Value(_) = c.val { + // FIXME(const_generics): we could probably do a better job here. + write!(output, "{:?}", c).unwrap() + } else if debug { + write!(output, "{:?}", c).unwrap() + } else { + bug!( + "DefPathBasedNames: trying to create const name for unexpected const: {:?}", + c, + ); } output.push_str(": "); self.push_type_name(c.ty, output, debug); diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 8a98a5d836..745f7d0276 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -17,6 +17,7 @@ use syntax::attr::{SignedInt, UnsignedInt}; use syntax::symbol::{kw, Symbol}; use std::cell::Cell; +use std::collections::BTreeMap; use std::fmt::{self, Write as _}; use std::ops::{Deref, DerefMut}; @@ -49,6 +50,24 @@ macro_rules! define_scoped_cx { thread_local! { static FORCE_IMPL_FILENAME_LINE: Cell = Cell::new(false); static SHOULD_PREFIX_WITH_CRATE: Cell = Cell::new(false); + static NO_QUERIES: Cell = Cell::new(false); +} + +/// Avoids running any queries during any prints that occur +/// during the closure. This may alter the appearance of some +/// types (e.g. forcing verbose printing for opaque types). +/// This method is used during some queries (e.g. `predicates_of` +/// for opaque types), to ensure that any debug printing that +/// occurs during the query computation does not end up recursively +/// calling the same query. +pub fn with_no_queries R, R>(f: F) -> R { + NO_QUERIES.with(|no_queries| { + let old = no_queries.get(); + no_queries.set(true); + let result = f(); + no_queries.set(old); + result + }) } /// Force us to name impls with just the filename/line number. We @@ -430,7 +449,7 @@ pub trait PrettyPrinter<'tcx>: p!(print(self_ty)); if let Some(trait_ref) = trait_ref { - p!(write(" as "), print(trait_ref)); + p!(write(" as "), print(trait_ref.print_only_trait_path())); } Ok(cx) }) @@ -449,7 +468,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("impl ")); if let Some(trait_ref) = trait_ref { - p!(print(trait_ref), write(" for ")); + p!(print(trait_ref.print_only_trait_path()), write(" for ")); } p!(print(self_ty)); @@ -466,13 +485,13 @@ pub trait PrettyPrinter<'tcx>: match ty.kind { ty::Bool => p!(write("bool")), ty::Char => p!(write("char")), - ty::Int(t) => p!(write("{}", t.ty_to_string())), - ty::Uint(t) => p!(write("{}", t.ty_to_string())), - ty::Float(t) => p!(write("{}", t.ty_to_string())), + ty::Int(t) => p!(write("{}", t.name_str())), + ty::Uint(t) => p!(write("{}", t.name_str())), + ty::Float(t) => p!(write("{}", t.name_str())), ty::RawPtr(ref tm) => { p!(write("*{} ", match tm.mutbl { - hir::MutMutable => "mut", - hir::MutImmutable => "const", + hir::Mutability::Mutable => "mut", + hir::Mutability::Immutable => "const", })); p!(print(tm.ty)) } @@ -556,61 +575,69 @@ pub trait PrettyPrinter<'tcx>: } ty::Opaque(def_id, substs) => { // FIXME(eddyb) print this with `print_def_path`. - if self.tcx().sess.verbose() { + // We use verbose printing in 'NO_QUERIES' mode, to + // avoid needing to call `predicates_of`. This should + // only affect certain debug messages (e.g. messages printed + // from `rustc::ty` during the computation of `tcx.predicates_of`), + // and should have no effect on any compiler output. + if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()) { p!(write("Opaque({:?}, {:?})", def_id, substs)); return Ok(self); } - let def_key = self.tcx().def_key(def_id); - if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - p!(write("{}", name)); - let mut substs = substs.iter(); - // FIXME(eddyb) print this with `print_def_path`. - if let Some(first) = substs.next() { - p!(write("::<")); - p!(print(first)); - for subst in substs { - p!(write(", "), print(subst)); + return Ok(with_no_queries(|| { + + let def_key = self.tcx().def_key(def_id); + if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { + p!(write("{}", name)); + let mut substs = substs.iter(); + // FIXME(eddyb) print this with `print_def_path`. + if let Some(first) = substs.next() { + p!(write("::<")); + p!(print(first)); + for subst in substs { + p!(write(", "), print(subst)); + } + p!(write(">")); } - p!(write(">")); + return Ok(self); } - return Ok(self); - } - // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); - - let mut first = true; - let mut is_sized = false; - p!(write("impl")); - for predicate in bounds.predicates { - if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { - is_sized = true; - continue; - } + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); + + let mut first = true; + let mut is_sized = false; + p!(write("impl")); + for predicate in bounds.predicates { + if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { + // Don't print +Sized, but rather +?Sized if absent. + if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { + is_sized = true; + continue; + } - p!( - write("{}", if first { " " } else { "+" }), - print(trait_ref)); - first = false; + p!( + write("{}", if first { " " } else { "+" }), + print(trait_ref.print_only_trait_path())); + first = false; + } } - } - if !is_sized { - p!(write("{}?Sized", if first { " " } else { "+" })); - } else if first { - p!(write(" Sized")); - } + if !is_sized { + p!(write("{}?Sized", if first { " " } else { "+" })); + } else if first { + p!(write(" Sized")); + } + Ok(self) + })?); } ty::Str => p!(write("str")), ty::Generator(did, substs, movability) => { let upvar_tys = substs.as_generator().upvar_tys(did, self.tcx()); let witness = substs.as_generator().witness(did, self.tcx()); - if movability == hir::GeneratorMovability::Movable { - p!(write("[generator")); - } else { - p!(write("[static generator")); + match movability { + hir::Movability::Movable => p!(write("[generator")), + hir::Movability::Static => p!(write("[static generator")), } // FIXME(eddyb) should use `def_span`. @@ -655,7 +682,7 @@ pub trait PrettyPrinter<'tcx>: // FIXME(eddyb) should use `def_span`. if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) { if self.tcx().sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", hir_id)); + p!(write("@"), print_def_path(did, substs)); } else { p!(write("@{:?}", self.tcx().hir().span(hir_id))); } @@ -700,7 +727,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("["), print(ty), write("; ")); if self.tcx().sess.verbose() { p!(write("{:?}", sz)); - } else if let ConstValue::Unevaluated(..) = sz.val { + } else if let ty::ConstKind::Unevaluated(..) = sz.val { // do not try to evalute unevaluated constants. If we are const evaluating an // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. @@ -862,11 +889,9 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } - let u8 = self.tcx().types.u8; - match (ct.val, &ct.ty.kind) { (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)), - (ConstValue::Unevaluated(did, substs), _) => { + (ty::ConstKind::Unevaluated(did, substs), _) => { match self.tcx().def_kind(did) { | Some(DefKind::Static) | Some(DefKind::Const) @@ -883,8 +908,33 @@ pub trait PrettyPrinter<'tcx>: }, } }, - (ConstValue::Infer(..), _) => p!(write("_: "), print(ct.ty)), - (ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)), + (ty::ConstKind::Infer(..), _) => p!(write("_: "), print(ct.ty)), + (ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)), + (ty::ConstKind::Value(value), _) => return self.pretty_print_const_value(value, ct.ty), + + _ => { + // fallback + p!(write("{:?} : ", ct.val), print(ct.ty)) + } + }; + Ok(self) + } + + fn pretty_print_const_value( + mut self, + ct: ConstValue<'tcx>, + ty: Ty<'tcx>, + ) -> Result { + define_scoped_cx!(self); + + if self.tcx().sess.verbose() { + p!(write("ConstValue({:?}: {:?})", ct, ty)); + return Ok(self); + } + + let u8 = self.tcx().types.u8; + + match (ct, &ty.kind) { (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) => p!(write("{}", if data == 0 { "false" } else { "true" })), (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) => @@ -895,10 +945,11 @@ pub trait PrettyPrinter<'tcx>: let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size(); let max = truncate(u128::max_value(), bit_size); + let ui_str = ui.name_str(); if data == max { - p!(write("std::{}::MAX", ui)) + p!(write("std::{}::MAX", ui_str)) } else { - p!(write("{}{}", data, ui)) + p!(write("{}{}", data, ui_str)) }; }, (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => { @@ -907,14 +958,15 @@ pub trait PrettyPrinter<'tcx>: let min = 1u128 << (bit_size - 1); let max = min - 1; - let ty = self.tcx().lift(&ct.ty).unwrap(); + let ty = self.tcx().lift(&ty).unwrap(); let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)) .unwrap() .size; + let i_str = i.name_str(); match data { - d if d == min => p!(write("std::{}::MIN", i)), - d if d == max => p!(write("std::{}::MAX", i)), - _ => p!(write("{}{}", sign_extend(data, size) as i128, i)) + d if d == min => p!(write("std::{}::MIN", i_str)), + d if d == max => p!(write("std::{}::MAX", i_str)), + _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)) } }, (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => @@ -928,8 +980,8 @@ pub trait PrettyPrinter<'tcx>: p!(print_value_path(instance.def_id(), instance.substs)); }, _ => { - let printed = if let ty::Ref(_, ref_ty, _) = ct.ty.kind { - let byte_str = match (ct.val, &ref_ty.kind) { + let printed = if let ty::Ref(_, ref_ty, _) = ty.kind { + let byte_str = match (ct, &ref_ty.kind) { (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); Some(self.tcx() @@ -956,7 +1008,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("\"")); true } else if let (ConstValue::Slice { data, start, end }, ty::Str) = - (ct.val, &ref_ty.kind) + (ct, &ref_ty.kind) { // The `inspect` here is okay since we checked the bounds, and there are no // relocations (we have an active `str` reference here). We don't use this @@ -974,7 +1026,7 @@ pub trait PrettyPrinter<'tcx>: }; if !printed { // fallback - p!(write("{:?} : ", ct.val), print(ct.ty)) + p!(write("{:?} : ", ct), print(ty)) } } }; @@ -1030,7 +1082,7 @@ impl FmtPrinter<'a, 'tcx, F> { } } -impl TyCtxt<'_> { +impl TyCtxt<'t> { // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always // (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(self, def_id: DefId) -> Namespace { @@ -1053,11 +1105,14 @@ impl TyCtxt<'_> { /// Returns a string identifying this `DefId`. This string is /// suitable for user output. pub fn def_path_str(self, def_id: DefId) -> String { + self.def_path_str_with_substs(def_id, &[]) + } + + pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String { let ns = self.guess_def_namespace(def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); - let _ = FmtPrinter::new(self, &mut s, ns) - .print_def_path(def_id, &[]); + let _ = FmtPrinter::new(self, &mut s, ns).print_def_path(def_id, substs); s } } @@ -1227,6 +1282,9 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { if !self.empty_path { write!(self, "::")?; } + if ast::Ident::from_str(&name).is_raw_guess() { + write!(self, "r#")?; + } write!(self, "{}", name)?; // FIXME(eddyb) this will print e.g. `{{closure}}#3`, but it @@ -1470,7 +1528,10 @@ impl FmtPrinter<'_, '_, F> { // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, // `region_index` and `used_region_names`. impl FmtPrinter<'_, 'tcx, F> { - pub fn pretty_in_binder(mut self, value: &ty::Binder) -> Result + pub fn name_all_regions( + mut self, + value: &ty::Binder, + ) -> Result<(Self, (T, BTreeMap>)), fmt::Error> where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { @@ -1503,8 +1564,7 @@ impl FmtPrinter<'_, 'tcx, F> { define_scoped_cx!(self); - let old_region_index = self.region_index; - let mut region_index = old_region_index; + let mut region_index = self.region_index; let new_value = self.tcx.replace_late_bound_regions(value, |br| { let _ = start_or_continue(&mut self, "for<", ", "); let br = match br { @@ -1526,12 +1586,21 @@ impl FmtPrinter<'_, 'tcx, F> { } }; self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) - }).0; + }); start_or_continue(&mut self, "", "> ")?; self.binder_depth += 1; self.region_index = region_index; - let mut inner = new_value.print(self)?; + Ok((self, new_value)) + } + + pub fn pretty_in_binder(self, value: &ty::Binder) -> Result + where + T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, + { + let old_region_index = self.region_index; + let (new, new_value) = self.name_all_regions(value)?; + let mut inner = new_value.0.print(new)?; inner.region_index = old_region_index; inner.binder_depth -= 1; Ok(inner) @@ -1630,6 +1699,30 @@ impl fmt::Display for ty::RegionKind { } } +/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only +/// the trait path. That is, it will print `Trait` instead of +/// `>`. +#[derive(Copy, Clone, TypeFoldable, Lift)] +pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); + +impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl ty::TraitRef<'tcx> { + pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> { + TraitRefPrintOnlyTraitPath(self) + } +} + +impl ty::Binder> { + pub fn print_only_trait_path(self) -> ty::Binder> { + self.map_bound(|tr| tr.print_only_trait_path()) + } +} + forward_display_to_print! { Ty<'tcx>, &'tcx ty::List>, @@ -1639,6 +1732,7 @@ forward_display_to_print! { // because `for<'tcx>` isn't possible yet. ty::Binder<&'tcx ty::List>>, ty::Binder>, + ty::Binder>, ty::Binder>, ty::Binder>, ty::Binder>, @@ -1666,15 +1760,14 @@ define_print_and_forward_display! { } ty::TypeAndMut<'tcx> { - p!(write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), - print(self.ty)) + p!(write("{}", self.mutbl.prefix_str()), print(self.ty)) } ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0)); let trait_ref = self.with_self_ty(cx.tcx(), dummy_self); - p!(print(trait_ref)) + p!(print(trait_ref.print_only_trait_path())) } ty::ExistentialProjection<'tcx> { @@ -1693,9 +1786,7 @@ define_print_and_forward_display! { } ty::FnSig<'tcx> { - if self.unsafety == hir::Unsafety::Unsafe { - p!(write("unsafe ")); - } + p!(write("{}", self.unsafety.prefix_str())); if self.abi != Abi::Rust { p!(write("extern {} ", self.abi)); @@ -1720,7 +1811,11 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - p!(print_def_path(self.def_id, self.substs)); + p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path())) + } + + TraitRefPrintOnlyTraitPath<'tcx> { + p!(print_def_path(self.0.def_id, self.0.substs)); } ty::ParamTy { @@ -1736,7 +1831,8 @@ define_print_and_forward_display! { } ty::TraitPredicate<'tcx> { - p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + p!(print(self.trait_ref.self_ty()), write(": "), + print(self.trait_ref.print_only_trait_path())) } ty::ProjectionPredicate<'tcx> { diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index c1c6a655d9..7e126459dc 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -6,7 +6,7 @@ use crate::ty::query::queries; use crate::ty::query::{Query, QueryName}; use crate::ty::query::QueryCache; use crate::ty::query::plumbing::CycleError; -use crate::util::profiling::ProfileCategory; +use rustc_data_structures::profiling::ProfileCategory; use std::borrow::Cow; use std::hash::Hash; diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index 391ea762a0..2f30b797fb 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -22,16 +22,6 @@ use { std::iter::FromIterator, }; -/// Indicates the state of a query for a given key in a query map. -pub(super) enum QueryResult<'tcx> { - /// An already executing query. The query job can be used to await for its completion. - Started(Lrc>), - - /// The query panicked. Queries trying to wait on this will raise a fatal error or - /// silently panic. - Poisoned, -} - /// Represents a span and a query key. #[derive(Clone, Debug)] pub struct QueryInfo<'tcx> { @@ -313,13 +303,8 @@ fn connected_to_root<'tcx>( return true; } - visit_waiters(query, |_, successor| { - if connected_to_root(successor, visited) { - Some(None) - } else { - None - } - }).is_some() + visit_waiters(query, |_, successor| connected_to_root(successor, visited).then_some(None)) + .is_some() } // Deterministically pick an query from a list diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 9b15ad560b..5b4a6ac8a2 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -39,10 +39,9 @@ use crate::ty::util::NeedsDrop; use crate::ty::subst::SubstsRef; use crate::util::nodemap::{DefIdSet, DefIdMap}; use crate::util::common::ErrorReported; -use crate::util::profiling::ProfileCategory::*; +use rustc_data_structures::profiling::ProfileCategory::*; use rustc_data_structures::svh::Svh; -use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_data_structures::fx::{FxIndexMap, FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::StableVec; @@ -57,7 +56,6 @@ use std::any::type_name; use syntax_pos::{Span, DUMMY_SP}; use syntax::attr; use syntax::ast; -use syntax::feature_gate; use syntax::symbol::Symbol; #[macro_use] diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 21a7cf00b2..4031eb6219 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -264,7 +264,7 @@ impl<'sess> OnDiskCache<'sess> { let sorted_cnums = sorted_cnums_including_local_crate(tcx); let prev_cnums: Vec<_> = sorted_cnums.iter() .map(|&cnum| { - let crate_name = tcx.original_crate_name(cnum).as_str().to_string(); + let crate_name = tcx.original_crate_name(cnum).to_string(); let crate_disambiguator = tcx.crate_disambiguator(cnum); (cnum.as_u32(), crate_name, crate_disambiguator) }) @@ -796,11 +796,6 @@ where } let span_data = span.data(); - - if span_data.hi < span_data.lo { - return TAG_INVALID_SPAN.encode(self); - } - let (file_lo, line_lo, col_lo) = match self.source_map .byte_pos_to_line_and_col(span_data.lo) { Some(pos) => pos, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 538154b035..fc55b665c1 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -7,25 +7,28 @@ use crate::ty::tls; use crate::ty::{self, TyCtxt}; use crate::ty::query::Query; use crate::ty::query::config::{QueryConfig, QueryDescription}; -use crate::ty::query::job::{QueryJob, QueryResult, QueryInfo}; +use crate::ty::query::job::{QueryJob, QueryInfo}; use errors::DiagnosticBuilder; use errors::Level; use errors::Diagnostic; use errors::FatalError; use errors::Handler; -use rustc_data_structures::fx::{FxHashMap}; +use rustc_data_structures::fx::{FxHasher, FxHashMap}; use rustc_data_structures::sync::{Lrc, Lock}; use rustc_data_structures::sharded::Sharded; use rustc_data_structures::thin_vec::ThinVec; #[cfg(not(parallel_compiler))] use rustc_data_structures::cold_path; +use std::hash::{Hash, Hasher}; use std::mem; use std::ptr; use std::collections::hash_map::Entry; use syntax_pos::Span; use syntax::source_map::DUMMY_SP; +use rustc_error_codes::*; + pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> { pub(super) results: FxHashMap>, pub(super) active: FxHashMap>, @@ -49,6 +52,16 @@ impl QueryValue { } } +/// Indicates the state of a query for a given key in a query map. +pub(super) enum QueryResult<'tcx> { + /// An already executing query. The query job can be used to await for its completion. + Started(Lrc>), + + /// The query panicked. Queries trying to wait on this will raise a fatal error or + /// silently panic. + Poisoned, +} + impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { fn default() -> QueryCache<'tcx, M> { QueryCache { @@ -80,8 +93,17 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> { let cache = Q::query_cache(tcx); loop { - let mut lock = cache.get_shard_by_value(key).lock(); - if let Some(value) = lock.results.get(key) { + // We compute the key's hash once and then use it for both the + // shard lookup and the hashmap lookup. This relies on the fact + // that both of them use `FxHasher`. + let mut state = FxHasher::default(); + key.hash(&mut state); + let key_hash = state.finish(); + + let mut lock = cache.get_shard_by_hash(key_hash).lock(); + if let Some((_, value)) = + lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key) + { tcx.prof.query_cache_hit(Q::NAME); let result = (value.value.clone(), value.index); #[cfg(debug_assertions)] @@ -664,15 +686,13 @@ macro_rules! define_queries_inner { [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => { use std::mem; - #[cfg(parallel_compiler)] - use ty::query::job::QueryResult; use rustc_data_structures::sharded::Sharded; use crate::{ rustc_data_structures::stable_hasher::HashStable, rustc_data_structures::stable_hasher::StableHasher, ich::StableHashingContext }; - use crate::util::profiling::ProfileCategory; + use rustc_data_structures::profiling::ProfileCategory; define_queries_struct! { tcx: $tcx, @@ -816,8 +836,20 @@ macro_rules! define_queries_inner { $($name),* } + impl rustc_data_structures::profiling::QueryName for QueryName { + fn discriminant(self) -> std::mem::Discriminant { + std::mem::discriminant(&self) + } + + fn as_str(self) -> &'static str { + QueryName::as_str(&self) + } + } + impl QueryName { - pub fn register_with_profiler(profiler: &crate::util::profiling::SelfProfiler) { + pub fn register_with_profiler( + profiler: &rustc_data_structures::profiling::SelfProfiler, + ) { $(profiler.register_query_name(QueryName::$name);)* } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 1da65f4b51..efdf40fd6b 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -121,8 +121,8 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { } else { let mutbl = a.mutbl; let variance = match mutbl { - ast::Mutability::MutImmutable => ty::Covariant, - ast::Mutability::MutMutable => ty::Invariant, + ast::Mutability::Immutable => ty::Covariant, + ast::Mutability::Mutable => ty::Invariant, }; let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?; Ok(ty::TypeAndMut { ty, mutbl }) @@ -281,7 +281,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { a: &ty::TraitRef<'tcx>, b: &ty::TraitRef<'tcx>, ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> { - // Different traits cannot be related + // Different traits cannot be related. if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { @@ -297,7 +297,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { a: &ty::ExistentialTraitRef<'tcx>, b: &ty::ExistentialTraitRef<'tcx>, ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> { - // Different traits cannot be related + // Different traits cannot be related. if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { @@ -307,15 +307,9 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, TypeFoldable)] struct GeneratorWitness<'tcx>(&'tcx ty::List>); -TupleStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> { - a - } -} - impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { fn relate>( relation: &mut R, @@ -561,51 +555,59 @@ pub fn super_relate_consts>( // and those that derive both `PartialEq` and `Eq`, corresponding // to `structural_match` types. let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) { - (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => { + (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { // The caller should handle these cases! bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) } - (ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => { + (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => { return Ok(a); } - (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => { + (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) if p1 == p2 => { return Ok(a); } - (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => { - if a_val == b_val { - Ok(ConstValue::Scalar(a_val)) - } else if let ty::FnPtr(_) = a.ty.kind { - let alloc_map = tcx.alloc_map.lock(); - let a_instance = alloc_map.unwrap_fn(a_val.to_ptr().unwrap().alloc_id); - let b_instance = alloc_map.unwrap_fn(b_val.to_ptr().unwrap().alloc_id); - if a_instance == b_instance { - Ok(ConstValue::Scalar(a_val)) - } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => { + let new_val = match (a_val, b_val) { + (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => { + if a_val == b_val { + Ok(ConstValue::Scalar(a_val)) + } else if let ty::FnPtr(_) = a.ty.kind { + let alloc_map = tcx.alloc_map.lock(); + let a_instance = alloc_map.unwrap_fn(a_val.to_ptr().unwrap().alloc_id); + let b_instance = alloc_map.unwrap_fn(b_val.to_ptr().unwrap().alloc_id); + if a_instance == b_instance { + Ok(ConstValue::Scalar(a_val)) + } else { + Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + } + } else { + Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + } } - } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) - } - } - (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => { - let a_bytes = get_slice_bytes(&tcx, a_val); - let b_bytes = get_slice_bytes(&tcx, b_val); - if a_bytes == b_bytes { - Ok(a_val) - } else { - Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) - } - } + (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => { + let a_bytes = get_slice_bytes(&tcx, a_val); + let b_bytes = get_slice_bytes(&tcx, b_val); + if a_bytes == b_bytes { + Ok(a_val) + } else { + Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + } + } + + // FIXME(const_generics): handle `ConstValue::ByRef`. + + _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), + }; - // FIXME(const_generics): handle `ConstValue::ByRef`. + new_val.map(ty::ConstKind::Value) + }, // FIXME(const_generics): this is wrong, as it is a projection - (ConstValue::Unevaluated(a_def_id, a_substs), - ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => { + (ty::ConstKind::Unevaluated(a_def_id, a_substs), + ty::ConstKind::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => { let substs = relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - Ok(ConstValue::Unevaluated(a_def_id, &substs)) + Ok(ty::ConstKind::Unevaluated(a_def_id, &substs)) } _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), }; diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 5d78d563e9..ce76a4c831 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1,17 +1,17 @@ //! This module contains implements of the `Lift` and `TypeFoldable` //! traits for various types in the Rust compiler. Most are written by -//! hand, though we've recently added some macros (e.g., -//! `BraceStructLiftImpl!`) to help with the tedium. +//! hand, though we've recently added some macros and proc-macros to help with the tedium. use crate::hir::def::Namespace; +use crate::hir::def_id::CRATE_DEF_INDEX; use crate::mir::ProjectionKind; -use crate::mir::interpret::ConstValue; +use crate::mir::interpret; use crate::ty::{self, Lift, Ty, TyCtxt, InferConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; + use rustc_index::vec::{IndexVec, Idx}; use smallvec::SmallVec; -use crate::mir::interpret; use std::fmt; use std::rc::Rc; @@ -96,8 +96,11 @@ impl fmt::Debug for ty::BoundRegion { match *self { ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), ty::BrNamed(did, name) => { - write!(f, "BrNamed({:?}:{:?}, {})", - did.krate, did.index, name) + if did.index == CRATE_DEF_INDEX { + write!(f, "BrNamed({})", name) + } else { + write!(f, "BrNamed({:?}, {})", did, name) + } } ty::BrEnv => write!(f, "BrEnv"), } @@ -224,10 +227,7 @@ impl fmt::Debug for ty::FloatVarValue { impl fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // FIXME(#59188) this is used across the compiler to print - // a `TraitRef` qualified (with the Self type explicit), - // instead of having a different way to make that choice. - write!(f, "<{} as {}>", self.self_ty(), self) + fmt::Display::fmt(self, f) } } @@ -303,7 +303,7 @@ CloneTypeFoldableAndLiftImpls! { ::syntax_pos::symbol::Symbol, crate::hir::def::Res, crate::hir::def_id::DefId, - crate::hir::InlineAsm, + crate::hir::InlineAsmInner, crate::hir::MatchSource, crate::hir::Mutability, crate::hir::Unsafety, @@ -780,27 +780,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { } } -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for ty::TypeAndMut<'a> { - type Lifted = ty::TypeAndMut<'tcx>; - ty, mutbl - } -} - -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for ty::Instance<'a> { - type Lifted = ty::Instance<'tcx>; - def, substs - } -} - -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for interpret::GlobalId<'a> { - type Lifted = interpret::GlobalId<'tcx>; - instance, promoted - } -} - /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. // @@ -916,10 +895,6 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { reveal, caller_bounds, def_id } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); @@ -931,14 +906,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> } } -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> { - (ty::ExistentialPredicate::Trait)(a), - (ty::ExistentialPredicate::Projection)(a), - (ty::ExistentialPredicate::AutoTrait)(a), - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); @@ -1125,41 +1092,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> { - ty, mutbl - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::GenSig<'tcx> { - yield_ty, return_ty - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> { - inputs_and_output, c_variadic, unsafety, abi - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> { def_id, substs } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> { def_id, substs } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ImplHeader<'tcx> { - impl_def_id, - self_ty, - trait_ref, - predicates, - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { fn super_fold_with>(&self, _folder: &mut F) -> Self { *self @@ -1178,47 +1110,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> { - substs, - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorSubsts<'tcx> { - substs, - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> { - kind, - target, - } -} - -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> { - (ty::adjustment::Adjust::NeverToAny), - (ty::adjustment::Adjust::Pointer)(a), - (ty::adjustment::Adjust::Deref)(a), - (ty::adjustment::Adjust::Borrow)(a), - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::OverloadedDeref<'tcx> { - region, mutbl, - } -} - -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { - (ty::adjustment::AutoBorrow::Ref)(a, b), - (ty::adjustment::AutoBorrow::RawPtr)(m), - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { // This code is hot enough that it's worth specializing for a list of @@ -1243,80 +1134,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } } -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { - (ty::Predicate::Trait)(a), - (ty::Predicate::Subtype)(a), - (ty::Predicate::RegionOutlives)(a), - (ty::Predicate::TypeOutlives)(a), - (ty::Predicate::Projection)(a), - (ty::Predicate::WellFormed)(a), - (ty::Predicate::ClosureKind)(a, b, c), - (ty::Predicate::ObjectSafe)(a), - (ty::Predicate::ConstEvaluatable)(a, b), - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> { - projection_ty, ty - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> { - ty, substs, item_def_id - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { - substs, item_def_id - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> { - predicates - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx, T> TypeFoldable<'tcx> for ty::ParamEnvAnd<'tcx, T> { - param_env, value - } where T: TypeFoldable<'tcx> -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> { - a_is_expected, a, b - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> { - trait_ref - } -} - -TupleStructTypeFoldableImpl! { - impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate { - a, b - } where T : TypeFoldable<'tcx>, U : TypeFoldable<'tcx>, -} - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> { - res, span, ty - } -} - -BraceStructTypeFoldableImpl! { - impl<'tcx, T> TypeFoldable<'tcx> for ty::error::ExpectedFound { - expected, found - } where T: TypeFoldable<'tcx> -} - impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { fn super_fold_with>(&self, folder: &mut F) -> Self { self.iter().map(|x| x.fold_with(folder)).collect() @@ -1327,34 +1144,6 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec } } -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { - (ty::error::TypeError::Mismatch), - (ty::error::TypeError::UnsafetyMismatch)(x), - (ty::error::TypeError::AbiMismatch)(x), - (ty::error::TypeError::Mutability), - (ty::error::TypeError::TupleSize)(x), - (ty::error::TypeError::FixedArraySize)(x), - (ty::error::TypeError::ArgCount), - (ty::error::TypeError::RegionsDoesNotOutlive)(a, b), - (ty::error::TypeError::RegionsInsufficientlyPolymorphic)(a, b), - (ty::error::TypeError::RegionsOverlyPolymorphic)(a, b), - (ty::error::TypeError::RegionsPlaceholderMismatch), - (ty::error::TypeError::IntMismatch)(x), - (ty::error::TypeError::FloatMismatch)(x), - (ty::error::TypeError::Traits)(x), - (ty::error::TypeError::VariadicMismatch)(x), - (ty::error::TypeError::CyclicTy)(t), - (ty::error::TypeError::ProjectionMismatched)(x), - (ty::error::TypeError::ProjectionBoundsLength)(x), - (ty::error::TypeError::Sorts)(x), - (ty::error::TypeError::ExistentialMismatch)(x), - (ty::error::TypeError::ConstMismatch)(x), - (ty::error::TypeError::IntrinsicCast), - (ty::error::TypeError::ObjectUnsafeCoercion)(x), - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { let ty = self.ty.fold_with(folder); @@ -1378,26 +1167,25 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { match *self { - ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)), - ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)), - ConstValue::Unevaluated(did, substs) - => ConstValue::Unevaluated(did, substs.fold_with(folder)), - ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(..) - | ConstValue::Scalar(..) | ConstValue::Slice { .. } => *self, - + ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), + ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), + ty::ConstKind::Unevaluated(did, substs) + => ty::ConstKind::Unevaluated(did, substs.fold_with(folder)), + ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(..) => *self, } } fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { - ConstValue::Infer(ic) => ic.visit_with(visitor), - ConstValue::Param(p) => p.visit_with(visitor), - ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor), - ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(_) - | ConstValue::Scalar(_) | ConstValue::Slice { .. } => false, + ty::ConstKind::Infer(ic) => ic.visit_with(visitor), + ty::ConstKind::Param(p) => p.visit_with(visitor), + ty::ConstKind::Unevaluated(_, substs) => substs.visit_with(visitor), + ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(_) => false, } } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3a9994ac64..6cb0d1e994 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2,14 +2,14 @@ #![allow(rustc::usage_of_ty_tykind)] +use self::InferTy::*; +use self::TyKind::*; + use crate::hir; use crate::hir::def_id::DefId; use crate::infer::canonical::Canonical; use crate::mir::interpret::ConstValue; use crate::middle::region; -use polonius_engine::Atom; -use rustc_index::vec::Idx; -use rustc_macros::HashStable; use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind}; use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable}; use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv}; @@ -17,27 +17,30 @@ use crate::ty::layout::VariantIdx; use crate::util::captures::Captures; use crate::mir::interpret::{Scalar, GlobalId}; +use polonius_engine::Atom; +use rustc_index::vec::Idx; +use rustc_macros::HashStable; +use rustc_target::spec::abi; use smallvec::SmallVec; use std::borrow::Cow; use std::cmp::Ordering; use std::marker::PhantomData; use std::ops::Range; -use rustc_target::spec::abi; use syntax::ast::{self, Ident}; use syntax::symbol::{kw, Symbol}; -use self::InferTy::*; -use self::TyKind::*; - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, - Hash, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive( + Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable, + HashStable, TypeFoldable, Lift, +)] pub struct TypeAndMut<'tcx> { pub ty: Ty<'tcx>, pub mutbl: hir::Mutability, } -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, - RustcEncodable, RustcDecodable, Copy, HashStable)] +#[derive( + Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy, HashStable, +)] /// A "free" region `fr` can be interpreted as "some region /// at least as big as the scope `fr.scope`". pub struct FreeRegion { @@ -45,8 +48,9 @@ pub struct FreeRegion { pub bound_region: BoundRegion, } -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, - RustcEncodable, RustcDecodable, Copy, HashStable)] +#[derive( + Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy, HashStable, +)] pub enum BoundRegion { /// An anonymous region parameter for a given fn (&T) BrAnon(u32), @@ -65,7 +69,7 @@ pub enum BoundRegion { impl BoundRegion { pub fn is_named(&self) -> bool { match *self { - BoundRegion::BrNamed(..) => true, + BoundRegion::BrNamed(_, name) => name != kw::UnderscoreLifetime, _ => false, } } @@ -162,7 +166,7 @@ pub enum TyKind<'tcx> { /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. - Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), + Generator(DefId, SubstsRef<'tcx>, hir::Movability), /// A type representin the types stored inside a generator. /// This should only appear in GeneratorInteriors. @@ -304,7 +308,7 @@ static_assert_size!(TyKind<'_>, 24); /// type parameters is similar, but the role of CK and CS are /// different. CK represents the "yield type" and CS represents the /// "return type" of the generator. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, TypeFoldable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function, /// concatenated with the types of the upvars. @@ -391,7 +395,7 @@ impl<'tcx> ClosureSubsts<'tcx> { } /// Similar to `ClosureSubsts`; see the above documentation for more. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, TypeFoldable)] pub struct GeneratorSubsts<'tcx> { pub substs: SubstsRef<'tcx>, } @@ -471,18 +475,18 @@ impl<'tcx> GeneratorSubsts<'tcx> { } impl<'tcx> GeneratorSubsts<'tcx> { - /// Generator have not been resumed yet + /// Generator has not been resumed yet. pub const UNRESUMED: usize = 0; - /// Generator has returned / is completed + /// Generator has returned or is completed. pub const RETURNED: usize = 1; - /// Generator has been poisoned + /// Generator has been poisoned. pub const POISONED: usize = 2; const UNRESUMED_NAME: &'static str = "Unresumed"; const RETURNED_NAME: &'static str = "Returned"; const POISONED_NAME: &'static str = "Panicked"; - /// The valid variant indices of this Generator. + /// The valid variant indices of this generator. #[inline] pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range { // FIXME requires optimized MIR @@ -490,7 +494,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { (VariantIdx::new(0)..VariantIdx::new(num_variants)) } - /// The discriminant for the given variant. Panics if the variant_index is + /// The discriminant for the given variant. Panics if the `variant_index` is /// out of range. #[inline] pub fn discriminant_for_variant( @@ -505,7 +509,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { Discr { val: variant_index.as_usize() as u128, ty: self.discr_ty(tcx) } } - /// The set of all discriminants for the Generator, enumerated with their + /// The set of all discriminants for the generator, enumerated with their /// variant indices. #[inline] pub fn discriminants( @@ -591,8 +595,8 @@ impl<'tcx> UpvarSubsts<'tcx> { } } -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, - RustcEncodable, RustcDecodable, HashStable)] +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub enum ExistentialPredicate<'tcx> { /// E.g., `Iterator`. Trait(ExistentialTraitRef<'tcx>), @@ -670,12 +674,12 @@ impl<'tcx> List> { pub fn principal(&self) -> Option> { match self[0] { ExistentialPredicate::Trait(tr) => Some(tr), - _ => None + _ => None, } } pub fn principal_def_id(&self) -> Option { - self.principal().map(|d| d.def_id) + self.principal().map(|trait_ref| trait_ref.def_id) } #[inline] @@ -684,7 +688,7 @@ impl<'tcx> List> { { self.iter().filter_map(|predicate| { match *predicate { - ExistentialPredicate::Projection(p) => Some(p), + ExistentialPredicate::Projection(projection) => Some(projection), _ => None, } }) @@ -694,8 +698,8 @@ impl<'tcx> List> { pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { self.iter().filter_map(|predicate| { match *predicate { - ExistentialPredicate::AutoTrait(d) => Some(d), - _ => None + ExistentialPredicate::AutoTrait(did) => Some(did), + _ => None, } }) } @@ -722,7 +726,8 @@ impl<'tcx> Binder<&'tcx List>> { } pub fn iter<'a>(&'a self) - -> impl DoubleEndedIterator>> + 'tcx { + -> impl DoubleEndedIterator>> + 'tcx + { self.skip_binder().iter().cloned().map(Binder::bind) } } @@ -742,7 +747,8 @@ impl<'tcx> Binder<&'tcx List>> { /// Note that a `TraitRef` introduces a level of region binding, to /// account for higher-ranked trait bounds like `T: for<'a> Foo<&'a U>` /// or higher-ranked object types. -#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct TraitRef<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, @@ -750,7 +756,7 @@ pub struct TraitRef<'tcx> { impl<'tcx> TraitRef<'tcx> { pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> { - TraitRef { def_id: def_id, substs: substs } + TraitRef { def_id, substs } } /// Returns a `TraitRef` of the form `P0: Foo` where `Pi` @@ -813,15 +819,15 @@ impl<'tcx> PolyTraitRef<'tcx> { /// /// The substitutions don't include the erased `Self`, only trait /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, - RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct ExistentialTraitRef<'tcx> { pub def_id: DefId, pub substs: SubstsRef<'tcx>, } impl<'tcx> ExistentialTraitRef<'tcx> { - pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator> + 'b { + pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator> + 'b { // Select only the "input types" from a trait-reference. For // now this is all the types that appear in the // trait-reference, but it should eventually exclude @@ -985,8 +991,8 @@ impl Binder { /// Represents the projection of an associated type. In explicit UFCS /// form this would be written `>::N`. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, - Hash, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct ProjectionTy<'tcx> { /// The parameters of the associated item. pub substs: SubstsRef<'tcx>, @@ -1033,7 +1039,7 @@ impl<'tcx> ProjectionTy<'tcx> { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, TypeFoldable)] pub struct GenSig<'tcx> { pub yield_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>, @@ -1056,8 +1062,8 @@ impl<'tcx> PolyGenSig<'tcx> { /// - `inputs`: is the list of arguments and their modes. /// - `output`: is the return type. /// - `c_variadic`: indicates whether this is a C-variadic function. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, - Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct FnSig<'tcx> { pub inputs_and_output: &'tcx List>, pub c_variadic: bool, @@ -1203,6 +1209,7 @@ rustc_index::newtype_index! { /// is the outer fn. /// /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index + #[derive(HashStable)] pub struct DebruijnIndex { DEBUG_FORMAT = "DebruijnIndex({})", const INNERMOST = 0, @@ -1294,7 +1301,7 @@ pub enum RegionKind { /// A region variable. Should not exist after typeck. ReVar(RegionVid), - /// A placeholder region - basically the higher-ranked version of ReFree. + /// A placeholder region -- basically, the higher-ranked version of `ReFree`. /// Should not exist after typeck. RePlaceholder(ty::PlaceholderRegion), @@ -1378,21 +1385,20 @@ rustc_index::newtype_index! { pub struct BoundVar { .. } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, + RustcEncodable, RustcDecodable, HashStable)] pub struct BoundTy { pub var: BoundVar, pub kind: BoundTyKind, } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, + RustcEncodable, RustcDecodable, HashStable)] pub enum BoundTyKind { Anon, Param(Symbol), } -impl_stable_hash_for!(struct BoundTy { var, kind }); -impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); - impl From for BoundTy { fn from(var: BoundVar) -> Self { BoundTy { @@ -1403,8 +1409,8 @@ impl From for BoundTy { } /// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, - Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable)] pub struct ExistentialProjection<'tcx> { pub item_def_id: DefId, pub substs: SubstsRef<'tcx>, @@ -1517,8 +1523,6 @@ impl DebruijnIndex { } } -impl_stable_hash_for!(struct DebruijnIndex { private }); - /// Region utilities impl RegionKind { /// Is this region named by the user? @@ -1808,23 +1812,33 @@ impl<'tcx> TyS<'tcx> { match self.kind { Array(ty, _) | Slice(ty) => ty, Str => tcx.mk_mach_uint(ast::UintTy::U8), - _ => bug!("sequence_element_type called on non-sequence value: {}", self), + _ => bug!("`sequence_element_type` called on non-sequence value: {}", self), } } pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind { - Adt(def, substs) => { - def.non_enum_variant().fields[0].ty(tcx, substs) - } - _ => bug!("simd_type called on invalid type") + Adt(def, substs) => def.non_enum_variant().fields[0].ty(tcx, substs), + _ => bug!("`simd_type` called on invalid type"), + } + } + + pub fn simd_size(&self, _tcx: TyCtxt<'tcx>) -> u64 { + // Parameter currently unused, but probably needed in the future to + // allow `#[repr(simd)] struct Simd([T; N]);`. + match self.kind { + Adt(def, _) => def.non_enum_variant().fields.len() as u64, + _ => bug!("`simd_size` called on invalid type"), } } - pub fn simd_size(&self, _cx: TyCtxt<'_>) -> usize { + pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { match self.kind { - Adt(def, _) => def.non_enum_variant().fields.len(), - _ => bug!("simd_size called on invalid type") + Adt(def, substs) => { + let variant = def.non_enum_variant(); + (variant.fields.len() as u64, variant.fields[0].ty(tcx, substs)) + } + _ => bug!("`simd_size_and_type` called on invalid type"), } } @@ -1839,8 +1853,8 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_mutable_ptr(&self) -> bool { match self.kind { - RawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) | - Ref(_, _, hir::Mutability::MutMutable) => true, + RawPtr(TypeAndMut { mutbl: hir::Mutability::Mutable, .. }) | + Ref(_, _, hir::Mutability::Mutable) => true, _ => false } } @@ -1885,7 +1899,7 @@ impl<'tcx> TyS<'tcx> { } } - /// panics if called on any type other than `Box` + /// Panics if called on any type other than `Box`. pub fn boxed_ty(&self) -> Ty<'tcx> { match self.kind { Adt(def, substs) if def.is_box() => substs.type_at(0), @@ -2030,7 +2044,7 @@ impl<'tcx> TyS<'tcx> { Adt(def, _) if def.is_box() => { Some(TypeAndMut { ty: self.boxed_ty(), - mutbl: hir::MutImmutable, + mutbl: hir::Mutability::Immutable, }) }, Ref(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl }), @@ -2105,7 +2119,8 @@ impl<'tcx> TyS<'tcx> { } /// If the type contains variants, returns the valid range of variant indices. - /// FIXME This requires the optimized MIR in the case of generators. + // + // FIXME: This requires the optimized MIR in the case of generators. #[inline] pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option> { match self.kind { @@ -2118,7 +2133,8 @@ impl<'tcx> TyS<'tcx> { /// If the type contains variants, returns the variant for `variant_index`. /// Panics if `variant_index` is out of range. - /// FIXME This requires the optimized MIR in the case of generators. + // + // FIXME: This requires the optimized MIR in the case of generators. #[inline] pub fn discriminant_for_variant( &self, @@ -2133,7 +2149,7 @@ impl<'tcx> TyS<'tcx> { } } - /// Push onto `out` the regions directly referenced from this type (but not + /// Pushes onto `out` the regions directly referenced from this type (but not /// types reachable from this type via `walk_tys`). This ignores late-bound /// regions binders. pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) { @@ -2246,7 +2262,7 @@ impl<'tcx> TyS<'tcx> { ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => - bug!("is_trivially_sized applied to unexpected type: {:?}", self), + bug!("`is_trivially_sized` applied to unexpected type: {:?}", self), } } } @@ -2257,17 +2273,17 @@ impl<'tcx> TyS<'tcx> { pub struct Const<'tcx> { pub ty: Ty<'tcx>, - pub val: ConstValue<'tcx>, + pub val: ConstKind<'tcx>, } #[cfg(target_arch = "x86_64")] -static_assert_size!(Const<'_>, 40); +static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { #[inline] pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self { tcx.mk_const(Self { - val: ConstValue::Scalar(val), + val: ConstKind::Value(ConstValue::Scalar(val)), ty, }) } @@ -2314,22 +2330,43 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> &Const<'tcx> { - // FIXME(const_generics): this doesn't work right now, - // because it tries to relate an `Infer` to a `Param`. + let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs| { + let param_env_and_substs = param_env.with_reveal_all().and(substs); + + // Avoid querying `tcx.const_eval(...)` with any e.g. inference vars. + if param_env_and_substs.has_local_value() { + return None; + } + + let (param_env, substs) = param_env_and_substs.into_parts(); + + // try to resolve e.g. associated constants to their definition on an impl + let instance = ty::Instance::resolve(tcx, param_env, did, substs)?; + let gid = GlobalId { + instance, + promoted: None, + }; + tcx.const_eval(param_env.and(gid)).ok() + }; + match self.val { - ConstValue::Unevaluated(did, substs) => { - // if `substs` has no unresolved components, use and empty param_env - let (param_env, substs) = param_env.with_reveal_all().and(substs).into_parts(); - // try to resolve e.g. associated constants to their definition on an impl - let instance = match ty::Instance::resolve(tcx, param_env, did, substs) { - Some(instance) => instance, - None => return self, - }; - let gid = GlobalId { - instance, - promoted: None, - }; - tcx.const_eval(param_env.and(gid)).unwrap_or(self) + ConstKind::Unevaluated(did, substs) => { + // HACK(eddyb) when substs contain e.g. inference variables, + // attempt using identity substs instead, that will succeed + // when the expression doesn't depend on any parameters. + // FIXME(eddyb) make `const_eval` a canonical query instead, + // that would properly handle inference variables in `substs`. + if substs.has_local_value() { + let identity_substs = InternalSubsts::identity_for_item(tcx, did); + // The `ParamEnv` needs to match the `identity_substs`. + let identity_param_env = tcx.param_env(did); + match try_const_eval(did, identity_param_env, identity_substs) { + Some(ct) => ct.subst(tcx, substs), + None => self, + } + } else { + try_const_eval(did, param_env, substs).unwrap_or(self) + } }, _ => self, } @@ -2363,6 +2400,49 @@ impl<'tcx> Const<'tcx> { impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} +/// Represents a constant in Rust. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, + RustcEncodable, RustcDecodable, Hash, HashStable)] +pub enum ConstKind<'tcx> { + /// A const generic parameter. + Param(ParamConst), + + /// Infer the value of the const. + Infer(InferConst<'tcx>), + + /// Bound const variable, used only when preparing a trait query. + Bound(DebruijnIndex, BoundVar), + + /// A placeholder const - universally quantified higher-ranked const. + Placeholder(ty::PlaceholderConst), + + /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other + /// variants when the code is monomorphic enough for that. + Unevaluated(DefId, SubstsRef<'tcx>), + + /// Used to hold computed value. + Value(ConstValue<'tcx>), +} + +#[cfg(target_arch = "x86_64")] +static_assert_size!(ConstKind<'_>, 40); + +impl<'tcx> ConstKind<'tcx> { + #[inline] + pub fn try_to_scalar(&self) -> Option { + if let ConstKind::Value(val) = self { + val.try_to_scalar() + } else { + None + } + } + + #[inline] + pub fn try_to_bits(&self, size: ty::layout::Size) -> Option { + self.try_to_scalar()?.to_bits(size).ok() + } +} + /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, HashStable)] diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 2972197909..a8a17fe9d7 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -4,7 +4,6 @@ use crate::hir::def_id::DefId; use crate::infer::canonical::Canonical; use crate::ty::{self, Lift, List, Ty, TyCtxt, ParamConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use crate::mir::interpret::ConstValue; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder}; @@ -234,7 +233,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { ty::GenericParamDefKind::Const => { tcx.mk_const(ty::Const { - val: ConstValue::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), + val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), ty: tcx.type_of(def_id), }).into() } @@ -578,7 +577,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { return c; } - if let ConstValue::Param(p) = c.val { + if let ty::ConstKind::Param(p) = c.val { self.const_for_param(p, c) } else { c.super_fold_with(self) @@ -731,7 +730,8 @@ pub type CanonicalUserSubsts<'tcx> = Canonical<'tcx, UserSubsts<'tcx>>; /// Stores the user-given substs to reach some fully qualified path /// (e.g., `::Item` or `::Item`). -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable, Lift)] pub struct UserSubsts<'tcx> { /// The substitutions for the item as given by the user. pub substs: SubstsRef<'tcx>, @@ -741,21 +741,6 @@ pub struct UserSubsts<'tcx> { pub user_self_ty: Option>, } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for UserSubsts<'tcx> { - substs, - user_self_ty, - } -} - -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for UserSubsts<'a> { - type Lifted = UserSubsts<'tcx>; - substs, - user_self_ty, - } -} - /// Specifies the user-given self type. In the case of a path that /// refers to a member in an inherent impl, this self type is /// sometimes needed to constrain the type parameters on the impl. For @@ -772,23 +757,9 @@ BraceStructLiftImpl! { /// the impl (with the substs from `UserSubsts`) and apply those to /// the self type, giving `Foo`. Finally, we unify that with /// the self type here, which contains `?A` to be `&'static u32` -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +#[derive(HashStable, TypeFoldable, Lift)] pub struct UserSelfTy<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, } - -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for UserSelfTy<'tcx> { - impl_def_id, - self_ty, - } -} - -BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for UserSelfTy<'a> { - type Lifted = UserSelfTy<'tcx>; - impl_def_id, - self_ty, - } -} diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 5555dace45..2b83cecf1e 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -12,7 +12,6 @@ use crate::ty::subst::{Subst, InternalSubsts, SubstsRef, GenericArgKind}; use crate::ty::query::TyCtxtAt; use crate::ty::TyKind::*; use crate::ty::layout::{Integer, IntegerExt}; -use crate::mir::interpret::ConstValue; use crate::util::common::ErrorReported; use crate::middle::lang_items; @@ -184,7 +183,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { // Now libcore provides that impl. ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | ty::Char | ty::RawPtr(..) | ty::Never | - ty::Ref(_, _, hir::MutImmutable) => return Ok(()), + ty::Ref(_, _, hir::Mutability::Immutable) => return Ok(()), ty::Adt(adt, substs) => (adt, substs), @@ -334,14 +333,14 @@ impl<'tcx> TyCtxt<'tcx> { ty } - /// Same as applying struct_tail on `source` and `target`, but only + /// Same as applying `struct_tail` on `source` and `target`, but only /// keeps going as long as the two types are instances of the same /// structure definitions. /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, /// whereas struct_tail produces `T`, and `Trait`, respectively. /// /// Should only be called if the types have no inference variables and do - /// not need their lifetimes preserved (e.g. as part of codegen); otherwise + /// not need their lifetimes preserved (e.g., as part of codegen); otherwise, /// normalization attempt may cause compiler bugs. pub fn struct_lockstep_tails_erasing_lifetimes(self, source: Ty<'tcx>, @@ -354,7 +353,7 @@ impl<'tcx> TyCtxt<'tcx> { source, target, |ty| tcx.normalize_erasing_regions(param_env, ty)) } - /// Same as applying struct_tail on `source` and `target`, but only + /// Same as applying `struct_tail` on `source` and `target`, but only /// keeps going as long as the two types are instances of the same /// structure definitions. /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, @@ -566,7 +565,7 @@ impl<'tcx> TyCtxt<'tcx> { !impl_generics.type_param(pt, self).pure_wrt_drop } GenericArgKind::Const(&ty::Const { - val: ConstValue::Param(ref pc), + val: ty::ConstKind::Param(ref pc), .. }) => { !impl_generics.const_param(pc, self).pure_wrt_drop @@ -680,7 +679,22 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if the node pointed to by `def_id` is a mutable `static` item. pub fn is_mutable_static(&self, def_id: DefId) -> bool { - self.static_mutability(def_id) == Some(hir::MutMutable) + self.static_mutability(def_id) == Some(hir::Mutability::Mutable) + } + + /// Get the type of the pointer to the static that we use in MIR. + pub fn static_ptr_ty(&self, def_id: DefId) -> Ty<'tcx> { + // Make sure that any constants in the static's type are evaluated. + let static_ty = self.normalize_erasing_regions( + ty::ParamEnv::empty(), + self.type_of(def_id), + ); + + if self.is_mutable_static(def_id) { + self.mk_mut_ptr(static_ty) + } else { + self.mk_imm_ref(self.lifetimes.re_erased, static_ty) + } } /// Expands the given impl trait type, stopping if the type is recursive. diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index f5b1902e3c..8d0f9a4716 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -3,7 +3,6 @@ use crate::ty::{self, Ty}; use smallvec::{self, SmallVec}; -use crate::mir::interpret::ConstValue; // The TypeWalker's stack is hot enough that it's worth going to some effort to // avoid heap allocations. @@ -75,7 +74,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => { } ty::Array(ty, len) => { - if let ConstValue::Unevaluated(_, substs) = len.val { + if let ty::ConstKind::Unevaluated(_, substs) = len.val { stack.extend(substs.types().rev()); } stack.push(len.ty); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 4ea01bf964..276fc8c1de 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -2,12 +2,12 @@ use crate::hir; use crate::hir::def_id::DefId; use crate::infer::InferCtxt; use crate::ty::subst::SubstsRef; -use crate::traits; +use crate::traits::{self, AssocTypeBoundData}; use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use std::iter::once; +use syntax::symbol::{kw, Ident}; use syntax_pos::Span; use crate::middle::lang_items; -use crate::mir::interpret::ConstValue; /// Returns the set of obligations needed to make `ty` well-formed. /// If `ty` contains unresolved inference variables, this may include @@ -176,6 +176,23 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { pred: &ty::Predicate<'_>, trait_assoc_items: ty::AssocItemsIterator<'_>, | { + let trait_item = tcx.hir().as_local_hir_id(trait_ref.def_id).and_then(|trait_id| { + tcx.hir().find(trait_id) + }); + let (trait_name, trait_generics) = match trait_item { + Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Trait(.., generics, _, _), + .. + })) | + Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::TraitAlias(generics, _), + .. + })) => (Some(ident), Some(generics)), + _ => (None, None), + }; + let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span)); match pred { ty::Predicate::Projection(proj) => { @@ -192,7 +209,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // LL | impl Bar for Foo { // | ---------------- in this `impl` item // LL | type Ok = (); - // | ^^^^^^^^^^^^^ expected u32, found () + // | ^^^^^^^^^^^^^ expected `u32`, found `()` // | // = note: expected type `u32` // found type `()` @@ -211,7 +228,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // LL | impl Bar for Foo { // | ---------------- in this `impl` item // LL | type Ok = (); - // | ^^^^^^^^^^^^^ expected u32, found () + // | ^^^^^^^^^^^^^ expected `u32`, found `()` // ... // LL | impl Bar2 for Foo2 { // | ---------------- in this `impl` item @@ -226,10 +243,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { item.ident == trait_assoc_item.ident }).next() { cause.span = impl_item.span; - cause.code = traits::AssocTypeBound( - item_span, - trait_assoc_item.ident.span, - ); + cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData { + impl_span: item_span, + original: trait_assoc_item.ident.span, + bounds: vec![], + })); } } } @@ -251,14 +269,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // LL | type Assoc = bool; // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` // - // FIXME: if the obligation comes from the where clause in the `trait`, we - // should point at it: + // If the obligation comes from the where clause in the `trait`, we point at it: // // error[E0277]: the trait bound `bool: Bar` is not satisfied // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 // | // | trait Foo where >::Assoc: Bar { - // | -------------------------- obligation set here + // | -------------------------- restricted in this bound // LL | type Assoc; // | ----- associated type defined here // ... @@ -278,11 +295,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .next() .map(|impl_item| (impl_item, trait_assoc_item))) { + let bounds = trait_generics.map(|generics| get_generic_bound_spans( + &generics, + trait_name, + trait_assoc_item.ident, + )).unwrap_or_else(Vec::new); cause.span = impl_item.span; - cause.code = traits::AssocTypeBound( - item_span, - trait_assoc_item.ident.span, - ); + cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData { + impl_span: item_span, + original: trait_assoc_item.ident.span, + bounds, + })); } } } @@ -339,7 +362,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes the obligations required for an array length to be WF /// into `self.out`. fn compute_array_len(&mut self, constant: ty::Const<'tcx>) { - if let ConstValue::Unevaluated(def_id, substs) = constant.val { + if let ty::ConstKind::Unevaluated(def_id, substs) = constant.val { let obligations = self.nominal_obligations(def_id, substs); self.out.extend(obligations); @@ -666,3 +689,56 @@ pub fn object_region_bounds<'tcx>( tcx.required_region_bounds(open_ty, predicates) } + +/// Find the span of a generic bound affecting an associated type. +fn get_generic_bound_spans( + generics: &hir::Generics, + trait_name: Option<&Ident>, + assoc_item_name: Ident, +) -> Vec { + let mut bounds = vec![]; + for clause in generics.where_clause.predicates.iter() { + if let hir::WherePredicate::BoundPredicate(pred) = clause { + match &pred.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(Some(ty), path)) => { + let mut s = path.segments.iter(); + if let (a, Some(b), None) = (s.next(), s.next(), s.next()) { + if a.map(|s| &s.ident) == trait_name + && b.ident == assoc_item_name + && is_self_path(&ty.kind) + { + // `::Bar` + bounds.push(pred.span); + } + } + } + hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => { + if segment.ident == assoc_item_name { + if is_self_path(&ty.kind) { + // `Self::Bar` + bounds.push(pred.span); + } + } + } + _ => {} + } + } + } + bounds +} + +fn is_self_path(kind: &hir::TyKind) -> bool { + match kind { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { + let mut s = path.segments.iter(); + if let (Some(segment), None) = (s.next(), s.next()) { + if segment.ident.name == kw::SelfUpper { + // `type(Self)` + return true; + } + } + } + _ => {} + } + false +} diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 3e52a6aa50..7515d30e46 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -7,7 +7,6 @@ use std::fmt::Debug; use std::time::{Duration, Instant}; use syntax::symbol::{Symbol, sym}; -use rustc_macros::HashStable; use crate::session::Session; #[cfg(test)] @@ -16,10 +15,7 @@ mod tests; // The name of the associated type for `Fn` return types. pub const FN_OUTPUT_NAME: Symbol = sym::Output; -// Useful type to use with `Result<>` indicate that an error has already -// been reported to the user, so no need to continue checking. -#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, HashStable)] -pub struct ErrorReported; +pub use errors::ErrorReported; thread_local!(static TIME_DEPTH: Cell = Cell::new(0)); @@ -92,15 +88,7 @@ pub fn print_time_passes_entry(do_it: bool, what: &str, dur: Duration) { what); } -// Hack up our own formatting for the duration to make it easier for scripts -// to parse (always use the same number of decimal places and the same unit). -pub fn duration_to_secs_str(dur: Duration) -> String { - const NANOS_PER_SEC: f64 = 1_000_000_000.0; - let secs = dur.as_secs() as f64 + - dur.subsec_nanos() as f64 / NANOS_PER_SEC; - - format!("{:.3}", secs) -} +pub use rustc_session::utils::duration_to_secs_str; pub fn to_readable_str(mut val: usize) -> String { let mut groups = vec![]; diff --git a/src/librustc_apfloat/Cargo.toml b/src/librustc_apfloat/Cargo.toml index 4fc15f99e4..726965e1e7 100644 --- a/src/librustc_apfloat/Cargo.toml +++ b/src/librustc_apfloat/Cargo.toml @@ -10,4 +10,4 @@ path = "lib.rs" [dependencies] bitflags = "1.2.1" -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 867bbd22cf..71cfacfa56 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -7,8 +7,28 @@ edition = "2018" [lib] name = "rustc_codegen_llvm" path = "lib.rs" -crate-type = ["dylib"] test = false +doctest = false [dependencies] +bitflags = "1.0" +flate2 = "1.0" +libc = "0.2" +log = "0.4" +rustc = { path = "../librustc" } +rustc-demangle = "0.1" +rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } +rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } +rustc_feature = { path = "../librustc_feature" } +rustc_fs_util = { path = "../librustc_fs_util" } +rustc_incremental = { path = "../librustc_incremental" } +rustc_index = { path = "../librustc_index" } rustc_llvm = { path = "../librustc_llvm" } +rustc_session = { path = "../librustc_session" } +rustc_target = { path = "../librustc_target" } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index ae5cfc4d97..2607a49732 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -1,16 +1,16 @@ -use crate::llvm::{self, AttributePlace}; use crate::builder::Builder; use crate::context::CodegenCx; +use crate::llvm::{self, AttributePlace}; use crate::type_::Type; +use crate::type_of::LayoutLlvmExt; use crate::value::Value; -use crate::type_of::{LayoutLlvmExt}; + use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::operand::OperandValue; -use rustc_target::abi::call::ArgType; - +use rustc::bug; use rustc_codegen_ssa::traits::*; - +use rustc_target::abi::call::ArgAbi; use rustc_target::abi::{HasDataLayout, LayoutOf}; use rustc::ty::{Ty}; use rustc::ty::layout::{self}; @@ -163,7 +163,7 @@ impl LlvmType for CastTarget { } } -pub trait ArgTypeExt<'ll, 'tcx> { +pub trait ArgAbiExt<'ll, 'tcx> { fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn store( &self, @@ -179,14 +179,14 @@ pub trait ArgTypeExt<'ll, 'tcx> { ); } -impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { +impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { /// Gets the LLVM type for a place of the original Rust type of /// this argument/return, i.e., the result of `type_of::type_of`. fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { self.layout.llvm_type(cx) } - /// Stores a direct/indirect value described by this ArgType into a + /// Stores a direct/indirect value described by this ArgAbi into a /// place for the original Rust type of this argument/return. /// Can be used for both storing formal arguments into Rust variables /// or results of call/invoke instructions into their destinations. @@ -202,7 +202,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { if self.is_sized_indirect() { OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst) } else if self.is_unsized_indirect() { - bug!("unsized ArgType must be handled through store_fn_arg"); + bug!("unsized `ArgAbi` must be handled through `store_fn_arg`"); } else if let PassMode::Cast(cast) = self.mode { // FIXME(eddyb): Figure out when the simpler Store is safe, clang // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. @@ -232,10 +232,10 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); bx.lifetime_start(llscratch, scratch_size); - // ...where we first store the value... + // ... where we first store the value... bx.store(val, llscratch, scratch_align); - // ...and then memcpy it to the intended destination. + // ... and then memcpy it to the intended destination. bx.memcpy( dst.llval, self.layout.align.abi, @@ -279,28 +279,28 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { } } -impl ArgTypeMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl ArgAbiMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn store_fn_arg( &mut self, - ty: &ArgType<'tcx, Ty<'tcx>>, + arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, idx: &mut usize, dst: PlaceRef<'tcx, Self::Value> ) { - ty.store_fn_arg(self, idx, dst) + arg_abi.store_fn_arg(self, idx, dst) } - fn store_arg_ty( + fn store_arg( &mut self, - ty: &ArgType<'tcx, Ty<'tcx>>, + arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, val: &'ll Value, dst: PlaceRef<'tcx, &'ll Value> ) { - ty.store(self, val, dst) + arg_abi.store(self, val, dst) } - fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> &'ll Type { - ty.memory_ty(self) + fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> &'ll Type { + arg_abi.memory_ty(self) } } -pub trait FnTypeLlvmExt<'tcx> { +pub trait FnAbiLlvmExt<'tcx> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; @@ -308,7 +308,7 @@ pub trait FnTypeLlvmExt<'tcx> { fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value); } -impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { +impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { let args_capacity: usize = self.args.iter().map(|arg| if arg.pad.is_some() { 1 } else { 0 } + @@ -373,7 +373,7 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { fn llvm_cconv(&self) -> llvm::CallConv { match self.conv { - Conv::C => llvm::CCallConv, + Conv::C | Conv::Rust => llvm::CCallConv, Conv::AmdGpuKernel => llvm::AmdGpuKernel, Conv::ArmAapcs => llvm::ArmAapcsCallConv, Conv::Msp430Intr => llvm::Msp430Intr, @@ -389,6 +389,11 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { } fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) { + // FIXME(eddyb) can this also be applied to callsites? + if self.ret.layout.abi.is_uninhabited() { + llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn); + } + let mut i = 0; let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| { attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty); @@ -478,10 +483,10 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> { impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn apply_attrs_callsite( &mut self, - ty: &FnType<'tcx, Ty<'tcx>>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value ) { - ty.apply_attrs_callsite(self, callsite) + fn_abi.apply_attrs_callsite(self, callsite) } fn get_param(&self, index: usize) -> Self::Value { diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index 11b6e0befa..e1d56b9be7 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -4,6 +4,7 @@ use crate::attributes; use libc::c_uint; use rustc::ty::TyCtxt; use syntax::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use rustc::bug; use crate::ModuleLlvm; use crate::llvm::{self, False, True}; diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index b68ee2cb44..fa43e08291 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -12,12 +12,12 @@ use syntax_pos::Span; use std::ffi::{CStr, CString}; use libc::{c_uint, c_char}; - +use log::debug; impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn codegen_inline_asm( &mut self, - ia: &hir::InlineAsm, + ia: &hir::InlineAsmInner, outputs: Vec>, mut inputs: Vec<&'ll Value>, span: Span, diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 6a36a4a50c..5479a1f314 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -2,19 +2,21 @@ use std::ffi::CString; -use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::Session; use rustc::session::config::{Sanitizer, OptLevel}; -use rustc::ty::{self, TyCtxt, PolyFnSig}; +use rustc::ty::{self, TyCtxt, Ty}; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::fx::FxHashMap; +use rustc_target::abi::call::Conv; +use rustc_data_structures::const_cstr; use rustc_target::spec::PanicStrategy; use rustc_codegen_ssa::traits::*; -use crate::abi::Abi; +use crate::abi::FnAbi; use crate::attributes; use crate::llvm::{self, Attribute}; use crate::llvm::AttributePlace::Function; @@ -26,7 +28,7 @@ use crate::value::Value; /// Mark LLVM function to use provided inline heuristic. #[inline] -pub fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { +fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { use self::InlineAttr::*; match inline { Hint => Attribute::InlineHint.apply_llfn(Function, val), @@ -58,7 +60,7 @@ fn unwind(val: &'ll Value, can_unwind: bool) { /// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue. #[inline] -pub fn naked(val: &'ll Value, is_naked: bool) { +fn naked(val: &'ll Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } @@ -72,7 +74,7 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) /// Tell LLVM what instrument function to insert. #[inline] -pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if cx.sess().instrument_mcount() { // Similar to `clang -pg` behavior. Handled by the // `post-inline-ee-instrument` LLVM pass. @@ -88,7 +90,7 @@ pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } } -pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Only use stack probes if the target specification indicates that we // should be using stack probes if !cx.sess().target.target.options.stack_probes { @@ -202,11 +204,10 @@ pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) { pub fn from_fn_attrs( cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, - id: Option, - sig: PolyFnSig<'tcx>, + instance: ty::Instance<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) { - let codegen_fn_attrs = id.map(|id| cx.tcx.codegen_fn_attrs(id)) - .unwrap_or_else(|| CodegenFnAttrs::new()); + let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); match codegen_fn_attrs.optimize { OptimizeAttr::None => { @@ -224,6 +225,11 @@ pub fn from_fn_attrs( } } + // FIXME(eddyb) consolidate these two `inline` calls (and avoid overwrites). + if instance.def.is_inline(cx.tcx) { + inline(cx, llfn, attributes::InlineAttr::Hint); + } + inline(cx, llfn, codegen_fn_attrs.inline); // The `uwtable` attribute according to LLVM is: @@ -276,8 +282,7 @@ pub fn from_fn_attrs( // Special attribute for allocator functions, which can't unwind. false } else { - let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - if sig.abi == Abi::Rust || sig.abi == Abi::RustCall { + if fn_abi.conv == Conv::Rust { // Any Rust method (or `extern "Rust" fn` or `extern // "rust-call" fn`) is explicitly allowed to unwind // (unless it has no-unwind attribute, handled above). @@ -314,7 +319,7 @@ pub fn from_fn_attrs( codegen_fn_attrs.target_features .iter() .map(|f| { - let feature = &*f.as_str(); + let feature = &f.as_str(); format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) }) ) @@ -331,16 +336,14 @@ pub fn from_fn_attrs( // Note that currently the `wasm-import-module` doesn't do anything, but // eventually LLVM 7 should read this and ferry the appropriate import // module to the output file. - if let Some(id) = id { - if cx.tcx.sess.target.target.arch == "wasm32" { - if let Some(module) = wasm_import_module(cx.tcx, id) { - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - const_cstr!("wasm-import-module"), - &module, - ); - } + if cx.tcx.sess.target.target.arch == "wasm32" { + if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + const_cstr!("wasm-import-module"), + &module, + ); } } } @@ -373,11 +376,7 @@ pub fn provide_extern(providers: &mut Providers<'_>) { let native_libs = tcx.native_libraries(cnum); let def_id_to_native_lib = native_libs.iter().filter_map(|lib| - if let Some(id) = lib.foreign_module { - Some((id, lib)) - } else { - None - } + lib.foreign_module.map(|id| (id, lib)) ).collect::>(); let mut ret = FxHashMap::default(); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index b3be3d09f1..0e4e4e2f98 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -4,19 +4,21 @@ use crate::back::write::{self, DiagnosticHandlers, with_llvm_pmb, save_temp_bitc use crate::llvm::archive_ro::ArchiveRO; use crate::llvm::{self, True, False}; use crate::{ModuleLlvm, LlvmCodegenBackend}; +use rustc::bug; use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{ModuleConfig, CodegenContext, FatLTOInput}; use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinShared, ThinModule}; use rustc_codegen_ssa::traits::*; -use errors::{FatalError, Handler}; +use rustc_errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; -use rustc::dep_graph::cgu_reuse_tracker::CguReuse; +use rustc_session::cgu_reuse_tracker::CguReuse; use rustc::hir::def_id::LOCAL_CRATE; use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::session::config::{self, Lto}; use rustc::util::common::time_ext; use rustc_data_structures::fx::FxHashMap; use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, ModuleKind}; +use log::{info, debug}; use std::ffi::{CStr, CString}; use std::ptr; @@ -541,7 +543,7 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext, debug!("running the pass manager"); unsafe { let pm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(module.module_llvm.tm, pm, module.module_llvm.llmod()); + llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm); if config.verify_llvm_ir { let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 52f3a1cbb5..796ea7aac3 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -10,26 +10,28 @@ use crate::type_::Type; use crate::context::{is_pie_binary, get_reloc_model}; use crate::common; use crate::LlvmCodegenBackend; +use rustc::bug; use rustc::hir::def_id::LOCAL_CRATE; use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler}; use rustc_codegen_ssa::traits::*; -use rustc::session::config::{self, OutputType, Passes, Lto, SwitchWithOptPath}; +use rustc::session::config::{self, OutputType, Passes, Lto, Sanitizer, SwitchWithOptPath}; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, CompiledModule}; use rustc::util::common::time_ext; use rustc_fs_util::{path_to_c_string, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; -use errors::{Handler, FatalError}; +use rustc_errors::{Handler, FatalError}; +use log::debug; -use std::ffi::{CString, CStr}; +use std::ffi::CString; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::str; use std::sync::Arc; use std::slice; -use libc::{c_uint, c_void, c_char, size_t}; +use libc::{c_int, c_uint, c_void, c_char, size_t}; pub const RELOC_MODEL_ARGS : [(&str, llvm::RelocMode); 7] = [ ("pic", llvm::RelocMode::PIC), @@ -55,7 +57,7 @@ pub const TLS_MODEL_ARGS : [(&str, llvm::ThreadLocalMode); 4] = [ ("local-exec", llvm::ThreadLocalMode::LocalExec), ]; -pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError { +pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError { match llvm::last_error() { Some(err) => handler.fatal(&format!("{}: {}", msg, err)), None => handler.fatal(&msg), @@ -63,7 +65,7 @@ pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError { } pub fn write_output_file( - handler: &errors::Handler, + handler: &rustc_errors::Handler, target: &'ll llvm::TargetMachine, pm: &llvm::PassManager<'ll>, m: &'ll llvm::Module, @@ -161,16 +163,17 @@ pub fn target_machine_factory(sess: &Session, optlvl: config::OptLevel, find_fea let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); let features = features.join(","); let features = CString::new(features).unwrap(); + let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname); let is_pie_binary = !find_features && is_pie_binary(sess); let trap_unreachable = sess.target.target.options.trap_unreachable; let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes; let asm_comments = sess.asm_comments(); - + let relax_elf_relocations = sess.target.target.options.relax_elf_relocations; Arc::new(move || { let tm = unsafe { llvm::LLVMRustCreateTargetMachine( - triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), + triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), abi.as_ptr(), code_model, reloc_model, opt_level, @@ -182,6 +185,7 @@ pub fn target_machine_factory(sess: &Session, optlvl: config::OptLevel, find_fea singlethread, asm_comments, emit_stack_size_section, + relax_elf_relocations, ) }; @@ -322,7 +326,7 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } - if config.opt_level.is_some() { + if let Some(opt_level) = config.opt_level { // Create the two optimizing pass managers. These mirror what clang // does, and are by populated by LLVM's default PassManagerBuilder. // Each manager has a different set of passes, but they also share @@ -362,29 +366,16 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, } } - for pass_name in &cgcx.plugin_passes { - if let Some(pass) = find_pass(pass_name) { - extra_passes.push(pass); - } else { - diag_handler.err(&format!("a plugin asked for LLVM pass \ - `{}` but LLVM does not \ - recognize it", pass_name)); - } - - if pass_name == "name-anon-globals" { - have_name_anon_globals_pass = true; - } - } + add_sanitizer_passes(config, &mut extra_passes); // Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need // to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise // we'll get errors in LLVM. let using_thin_buffers = config.bitcode_needed(); if !config.no_prepopulate_passes { - llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); - llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); - let opt_level = config.opt_level.map(|x| to_llvm_opt_settings(x).0) - .unwrap_or(llvm::CodeGenOptLevel::None); + llvm::LLVMAddAnalysisPasses(tm, fpm); + llvm::LLVMAddAnalysisPasses(tm, mpm); + let opt_level = to_llvm_opt_settings(opt_level).0; let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal || (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled()); with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { @@ -448,6 +439,31 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, Ok(()) } +unsafe fn add_sanitizer_passes(config: &ModuleConfig, + passes: &mut Vec<&'static mut llvm::Pass>) { + + let sanitizer = match &config.sanitizer { + None => return, + Some(s) => s, + }; + + let recover = config.sanitizer_recover.contains(sanitizer); + match sanitizer { + Sanitizer::Address => { + passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover)); + passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover)); + } + Sanitizer::Memory => { + let track_origins = config.sanitizer_memory_track_origins as c_int; + passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover)); + } + Sanitizer::Thread => { + passes.push(llvm::LLVMRustCreateThreadSanitizerPass()); + } + Sanitizer::Leak => {} + } +} + pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &Handler, module: ModuleCodegen, @@ -482,7 +498,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, where F: FnOnce(&'ll mut PassManager<'ll>) -> R, { let cpm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); + llvm::LLVMAddAnalysisPasses(tm, cpm); llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); f(cpm) } @@ -574,14 +590,11 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, cursor.position() as size_t } - with_codegen(tm, llmod, config.no_builtins, |cpm| { - let result = - llvm::LLVMRustPrintModule(cpm, llmod, out_c.as_ptr(), demangle_callback); - llvm::LLVMDisposePassManager(cpm); - result.into_result().map_err(|()| { - let msg = format!("failed to write LLVM IR to {}", out.display()); - llvm_err(diag_handler, &msg) - }) + let result = + llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback); + result.into_result().map_err(|()| { + let msg = format!("failed to write LLVM IR to {}", out.display()); + llvm_err(diag_handler, &msg) })?; } @@ -822,8 +835,8 @@ fn create_msvc_imps( }) .filter_map(|val| { // Exclude some symbols that we know are not Rust symbols. - let name = CStr::from_ptr(llvm::LLVMGetValueName(val)); - if ignored(name.to_bytes()) { + let name = llvm::get_value_name(val); + if ignored(name) { None } else { Some((val, name)) @@ -831,7 +844,7 @@ fn create_msvc_imps( }) .map(move |(val, name)| { let mut imp_name = prefix.as_bytes().to_vec(); - imp_name.extend(name.to_bytes()); + imp_name.extend(name); let imp_name = CString::new(imp_name).unwrap(); (imp_name, val) }) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 312c41b88b..7509584df2 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -23,6 +23,8 @@ use std::ffi::CStr; use std::ops::{Deref, Range}; use std::ptr; use std::iter::TrustedLen; +use rustc_data_structures::const_cstr; +use log::debug; // All Builders must have an llfn associated with them #[must_use] @@ -325,8 +327,8 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { use rustc::ty::{Int, Uint}; let new_kind = match ty.kind { - Int(Isize) => Int(self.tcx.sess.target.isize_ty), - Uint(Usize) => Uint(self.tcx.sess.target.usize_ty), + Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.ptr_width)), + Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.ptr_width)), ref t @ Uint(_) | ref t @ Int(_) => t.clone(), _ => panic!("tried to get overflow intrinsic for op applied to non-int type") }; diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 08fa23f2a7..c0be87b117 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -4,14 +4,16 @@ //! and methods are represented as just a fn ptr and not a full //! closure. +use crate::abi::{FnAbi, FnAbiLlvmExt}; use crate::attributes; use crate::llvm; use crate::context::CodegenCx; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use log::debug; use rustc::ty::{TypeFoldable, Instance}; -use rustc::ty::layout::{LayoutOf, HasTyCtxt}; +use rustc::ty::layout::{FnAbiExt, HasTyCtxt}; /// Codegens a reference to a fn/method item, monomorphizing and /// inlining as it goes. @@ -32,19 +34,19 @@ pub fn get_fn( assert!(!instance.substs.has_escaping_bound_vars()); assert!(!instance.substs.has_param_types()); - let sig = instance.fn_sig(cx.tcx()); if let Some(&llfn) = cx.instances.borrow().get(&instance) { return llfn; } let sym = tcx.symbol_name(instance).name.as_str(); - debug!("get_fn({:?}: {:?}) => {}", instance, sig, sym); + debug!("get_fn({:?}: {:?}) => {}", instance, instance.ty(cx.tcx()), sym); - // Create a fn pointer with the substituted signature. - let fn_ptr_ty = tcx.mk_fn_ptr(sig); - let llptrty = cx.backend_type(cx.layout_of(fn_ptr_ty)); + let fn_abi = FnAbi::of_instance(cx, instance, &[]); let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { + // Create a fn pointer with the new signature. + let llptrty = fn_abi.ptr_to_llvm_type(cx); + // This is subtle and surprising, but sometimes we have to bitcast // the resulting fn pointer. The reason has to do with external // functions. If you have two crates that both bind the same C @@ -76,14 +78,10 @@ pub fn get_fn( llfn } } else { - let llfn = cx.declare_fn(&sym, sig); - assert_eq!(cx.val_ty(llfn), llptrty); + let llfn = cx.declare_fn(&sym, &fn_abi); debug!("get_fn: not casting pointer!"); - if instance.def.is_inline(tcx) { - attributes::inline(cx, llfn, attributes::InlineAttr::Hint); - } - attributes::from_fn_attrs(cx, llfn, Some(instance.def.def_id()), sig); + attributes::from_fn_attrs(cx, llfn, instance, &fn_abi); let instance_def_id = instance.def_id(); diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index f38f9dfecd..ff03c1f76d 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -8,6 +8,8 @@ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use rustc::bug; +use log::debug; use crate::consts::const_alloc_to_llvm; use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size}; @@ -245,11 +247,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { let (mut lo, mut hi) = (0u64, 0u64); let success = llvm::LLVMRustConstInt128Get(v, sign_ext, &mut hi, &mut lo); - if success { - Some(hi_lo_to_u128(lo, hi)) - } else { - None - } + success.then_some(hi_lo_to_u128(lo, hi)) }) } diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index fd7054a5a0..11a105c182 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -16,12 +16,14 @@ use rustc::ty::{self, Ty, Instance}; use rustc_codegen_ssa::traits::*; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; +use rustc::{bug, span_bug}; +use log::debug; use rustc::ty::layout::{self, Size, Align, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; -use std::ffi::{CStr, CString}; +use std::ffi::CStr; pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); @@ -88,9 +90,9 @@ pub fn codegen_static_initializer( let static_ = cx.tcx.const_eval(param_env.and(cid))?; let alloc = match static_.val { - ConstValue::ByRef { + ty::ConstKind::Value(ConstValue::ByRef { alloc, offset, - } if offset.bytes() == 0 => { + }) if offset.bytes() == 0 => { alloc }, _ => bug!("static const eval returned {:#?}", static_), @@ -233,11 +235,13 @@ impl CodegenCx<'ll, 'tcx> { ref attrs, span, kind: hir::ItemKind::Static(..), .. }) => { let sym_str = sym.as_str(); - if self.get_declared_value(&sym_str).is_some() { - span_bug!(span, "Conflicting symbol names for static?"); + if let Some(g) = self.get_declared_value(&sym_str) { + if self.val_ty(g) != self.type_ptr_to(llty) { + span_bug!(span, "Conflicting types for static"); + } } - let g = self.define_global(&sym_str, llty).unwrap(); + let g = self.declare_global(&sym_str, llty); if !self.tcx.is_reachable_non_generic(def_id) { unsafe { @@ -390,16 +394,14 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { } else { // If we created the global with the wrong type, // correct the type. - let empty_string = const_cstr!(""); - let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g)); - let name_string = CString::new(name_str_ref.to_bytes()).unwrap(); - llvm::LLVMSetValueName(g, empty_string.as_ptr()); + let name = llvm::get_value_name(g).to_vec(); + llvm::set_value_name(g, b""); let linkage = llvm::LLVMRustGetLinkage(g); let visibility = llvm::LLVMRustGetVisibility(g); let new_g = llvm::LLVMRustGetOrInsertGlobal( - self.llmod, name_string.as_ptr(), val_llty); + self.llmod, name.as_ptr().cast(), name.len(), val_llty); llvm::LLVMRustSetLinkage(new_g, linkage); llvm::LLVMRustSetVisibility(new_g, visibility); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 2da9387717..2c894a5d74 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -1,3 +1,4 @@ +use crate::abi::FnAbi; use crate::attributes; use crate::llvm; use crate::llvm_util; @@ -11,17 +12,19 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; use rustc_data_structures::small_c_str::SmallCStr; +use rustc::bug; use rustc::mir::mono::CodegenUnit; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; use rustc::ty::layout::{ - LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv + FnAbiExt, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv }; use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; use rustc_codegen_ssa::base::wants_msvc_seh; use crate::callee::get_fn; +use rustc_data_structures::const_cstr; use std::ffi::CStr; use std::cell::{Cell, RefCell}; @@ -203,6 +206,10 @@ pub unsafe fn create_module( let llvm_target = SmallCStr::new(&sess.target.target.llvm_target); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); + if get_reloc_model(sess) == llvm::RelocMode::PIC { + llvm::LLVMRustSetModulePICLevel(llmod); + } + if is_pie_binary(sess) { llvm::LLVMRustSetModulePIELevel(llmod); } @@ -416,7 +423,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { Abi::C )); - let llfn = self.declare_fn("rust_eh_unwind_resume", sig); + let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]); + let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi); attributes::apply_target_cpu_attr(self, llfn); unwresume.set(Some(llfn)); llfn diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index 6ee76b71fc..91d5a22b02 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -23,12 +23,10 @@ pub fn compute_mir_scopes( ) { // Find all the scopes with variables defined in them. let mut has_variables = BitSet::new_empty(mir.source_scopes.len()); - // FIXME(eddyb) base this on `decl.name`, or even better, on debuginfo. // FIXME(eddyb) take into account that arguments always have debuginfo, // irrespective of their name (assuming full debuginfo is enabled). - for var in mir.vars_iter() { - let decl = &mir.local_decls[var]; - has_variables.insert(decl.visibility_scope); + for var_debug_info in &mir.var_debug_info { + has_variables.insert(var_debug_info.source_info.scope); } // Instantiate all scopes. diff --git a/src/librustc_codegen_llvm/debuginfo/doc.rs b/src/librustc_codegen_llvm/debuginfo/doc.rs index daccfc9b24..b3a8fa2988 100644 --- a/src/librustc_codegen_llvm/debuginfo/doc.rs +++ b/src/librustc_codegen_llvm/debuginfo/doc.rs @@ -140,7 +140,7 @@ //! In order for link-time optimization to work properly, LLVM needs a unique //! type identifier that tells it across compilation units which types are the //! same as others. This type identifier is created by -//! TypeMap::get_unique_type_id_of_type() using the following algorithm: +//! `TypeMap::get_unique_type_id_of_type()` using the following algorithm: //! //! (1) Primitive types have their name as ID //! (2) Structs, enums and traits have a multipart identifier diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 9ed1c1730a..739437ac27 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -7,6 +7,7 @@ use crate::builder::Builder; use crate::value::Value; use rustc::session::config::DebugInfo; use rustc_codegen_ssa::traits::*; +use rustc::bug; use syntax::attr; use syntax::symbol::sym; diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index f0148a21ae..8327ff257c 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -7,23 +7,23 @@ use super::utils::{debug_context, DIB, span_start, use super::namespace::mangled_name_of_instance; use super::type_names::compute_debuginfo_type_name; use super::CrateDebugContext; -use crate::abi; -use crate::value::Value; -use rustc_codegen_ssa::traits::*; +use crate::abi; +use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DIArray, DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock, DIFlags, DebugEmissionKind}; use crate::llvm_util; +use crate::value::Value; -use crate::common::CodegenCx; +use rustc_codegen_ssa::traits::*; +use rustc_index::vec::{Idx, IndexVec}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::ich::NodeIdHashingMode; -use rustc::mir::Field; -use rustc::mir::GeneratorLayout; +use rustc::mir::{self, Field, GeneratorLayout}; use rustc::mir::interpret::truncate; use rustc_data_structures::fingerprint::Fingerprint; use rustc::ty::Instance; @@ -35,7 +35,13 @@ use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path_to_c_string; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_data_structures::const_cstr; use rustc_target::abi::HasDataLayout; +use syntax::ast; +use syntax::symbol::{Interner, Symbol}; +use syntax_pos::{self, Span, FileName}; +use rustc::{bug, span_bug}; +use log::debug; use libc::{c_uint, c_longlong}; use std::collections::hash_map::Entry; @@ -45,9 +51,6 @@ use std::hash::{Hash, Hasher}; use std::iter; use std::ptr; use std::path::{Path, PathBuf}; -use syntax::ast; -use syntax::symbol::{Interner, Symbol}; -use syntax_pos::{self, Span, FileName}; impl PartialEq for llvm::Metadata { fn eq(&self, other: &Self) -> bool { @@ -70,7 +73,7 @@ impl fmt::Debug for llvm::Metadata { } // From DWARF 5. -// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1 +// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1. const DW_LANG_RUST: c_uint = 0x1c; #[allow(non_upper_case_globals)] const DW_ATE_boolean: c_uint = 0x02; @@ -91,70 +94,70 @@ pub const NO_SCOPE_METADATA: Option<&DIScope> = None; #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] pub struct UniqueTypeId(ast::Name); -// The TypeMap is where the CrateDebugContext holds the type metadata nodes -// created so far. The metadata nodes are indexed by UniqueTypeId, and, for -// faster lookup, also by Ty. The TypeMap is responsible for creating -// UniqueTypeIds. +/// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes +/// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for +/// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating +/// `UniqueTypeId`s. #[derive(Default)] pub struct TypeMap<'ll, 'tcx> { - // The UniqueTypeIds created so far + /// The `UniqueTypeId`s created so far. unique_id_interner: Interner, - // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping. + /// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping. unique_id_to_metadata: FxHashMap, - // A map from types to debuginfo metadata. This is a N:1 mapping. + /// A map from types to debuginfo metadata. This is an N:1 mapping. type_to_metadata: FxHashMap, &'ll DIType>, - // A map from types to UniqueTypeId. This is a N:1 mapping. + /// A map from types to `UniqueTypeId`. This is an N:1 mapping. type_to_unique_id: FxHashMap, UniqueTypeId> } impl TypeMap<'ll, 'tcx> { - // Adds a Ty to metadata mapping to the TypeMap. The method will fail if - // the mapping already exists. + /// Adds a Ty to metadata mapping to the TypeMap. The method will fail if + /// the mapping already exists. fn register_type_with_metadata( &mut self, type_: Ty<'tcx>, metadata: &'ll DIType, ) { if self.type_to_metadata.insert(type_, metadata).is_some() { - bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_); + bug!("type metadata for `Ty` '{}' is already in the `TypeMap`!", type_); } } - // Removes a Ty to metadata mapping - // This is useful when computing the metadata for a potentially - // recursive type (e.g. a function ptr of the form: - // - // fn foo() -> impl Copy { foo } - // - // This kind of type cannot be properly represented - // via LLVM debuginfo. As a workaround, - // we register a temporary Ty to metadata mapping - // for the function before we compute its actual metadata. - // If the metadata computation ends up recursing back to the - // original function, it will use the temporary mapping - // for the inner self-reference, preventing us from - // recursing forever. - // - // This function is used to remove the temporary metadata - // mapping after we've computed the actual metadata + /// Removes a `Ty`-to-metadata mapping. + /// This is useful when computing the metadata for a potentially + /// recursive type (e.g., a function pointer of the form: + /// + /// fn foo() -> impl Copy { foo } + /// + /// This kind of type cannot be properly represented + /// via LLVM debuginfo. As a workaround, + /// we register a temporary Ty to metadata mapping + /// for the function before we compute its actual metadata. + /// If the metadata computation ends up recursing back to the + /// original function, it will use the temporary mapping + /// for the inner self-reference, preventing us from + /// recursing forever. + /// + /// This function is used to remove the temporary metadata + /// mapping after we've computed the actual metadata. fn remove_type( &mut self, type_: Ty<'tcx>, ) { if self.type_to_metadata.remove(type_).is_none() { - bug!("Type metadata Ty '{}' is not in the TypeMap!", type_); + bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", type_); } } - // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will - // fail if the mapping already exists. + /// Adds a `UniqueTypeId` to metadata mapping to the `TypeMap`. The method will + /// fail if the mapping already exists. fn register_unique_id_with_metadata( &mut self, unique_type_id: UniqueTypeId, metadata: &'ll DIType, ) { if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() { - bug!("Type metadata for unique id '{}' is already in the TypeMap!", + bug!("type metadata for unique ID '{}' is already in the `TypeMap`!", self.get_unique_type_id_as_string(unique_type_id)); } } @@ -167,23 +170,23 @@ impl TypeMap<'ll, 'tcx> { self.unique_id_to_metadata.get(&unique_type_id).cloned() } - // Get the string representation of a UniqueTypeId. This method will fail if - // the id is unknown. + /// Gets the string representation of a `UniqueTypeId`. This method will fail if + /// the ID is unknown. fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str { let UniqueTypeId(interner_key) = unique_type_id; self.unique_id_interner.get(interner_key) } - // Get the UniqueTypeId for the given type. If the UniqueTypeId for the given - // type has been requested before, this is just a table lookup. Otherwise an - // ID will be generated and stored for later lookup. + /// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given + /// type has been requested before, this is just a table lookup. Otherwise, an + /// ID will be generated and stored for later lookup. fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>, type_: Ty<'tcx>) -> UniqueTypeId { - // Let's see if we already have something in the cache + // Let's see if we already have something in the cache. if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() { return unique_type_id; } - // if not, generate one + // If not, generate one. // The hasher we are using to generate the UniqueTypeId. We want // something that provides more than the 64 bits of the DefaultHasher. @@ -203,9 +206,9 @@ impl TypeMap<'ll, 'tcx> { return UniqueTypeId(key); } - // Get the UniqueTypeId for an enum variant. Enum variants are not really - // types of their own, so they need special handling. We still need a - // UniqueTypeId for them, since to debuginfo they *are* real types. + /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really + /// types of their own, so they need special handling. We still need a + /// `UniqueTypeId` for them, since to debuginfo they *are* real types. fn get_unique_type_id_of_enum_variant<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>, enum_type: Ty<'tcx>, @@ -219,9 +222,9 @@ impl TypeMap<'ll, 'tcx> { UniqueTypeId(interner_key) } - // Get the unique type id string for an enum variant part. - // Variant parts are not types and shouldn't really have their own id, - // but it makes set_members_of_composite_type() simpler. + /// Gets the unique type ID string for an enum variant part. + /// Variant parts are not types and shouldn't really have their own ID, + /// but it makes `set_members_of_composite_type()` simpler. fn get_unique_type_id_str_of_enum_variant_part(&mut self, enum_type_id: UniqueTypeId) -> &str { let variant_part_type_id = format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id)); @@ -230,11 +233,11 @@ impl TypeMap<'ll, 'tcx> { } } -// A description of some recursive type. It can either be already finished (as -// with FinalMetadata) or it is not yet finished, but contains all information -// needed to generate the missing parts of the description. See the -// documentation section on Recursive Types at the top of this file for more -// information. +/// A description of some recursive type. It can either be already finished (as +/// with `FinalMetadata`) or it is not yet finished, but contains all information +/// needed to generate the missing parts of the description. See the +/// documentation section on Recursive Types at the top of this file for more +/// information. enum RecursiveTypeDescription<'ll, 'tcx> { UnfinishedMetadata { unfinished_type: Ty<'tcx>, @@ -255,7 +258,7 @@ fn create_and_register_recursive_type_forward_declaration( member_description_factory: MemberDescriptionFactory<'ll, 'tcx>, ) -> RecursiveTypeDescription<'ll, 'tcx> { - // Insert the stub into the TypeMap in order to allow for recursive references + // Insert the stub into the `TypeMap` in order to allow for recursive references. let mut type_map = debug_context(cx).type_map.borrow_mut(); type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub); type_map.register_type_with_metadata(unfinished_type, metadata_stub); @@ -270,9 +273,9 @@ fn create_and_register_recursive_type_forward_declaration( } impl RecursiveTypeDescription<'ll, 'tcx> { - // Finishes up the description of the type in question (mostly by providing - // descriptions of the fields of the given type) and returns the final type - // metadata. + /// Finishes up the description of the type in question (mostly by providing + /// descriptions of the fields of the given type) and returns the final type + /// metadata. fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> { match *self { FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false), @@ -287,7 +290,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> { // the TypeMap so that recursive references are possible. This // will always be the case if the RecursiveTypeDescription has // been properly created through the - // create_and_register_recursive_type_forward_declaration() + // `create_and_register_recursive_type_forward_declaration()` // function. { let type_map = debug_context(cx).type_map.borrow(); @@ -314,8 +317,8 @@ impl RecursiveTypeDescription<'ll, 'tcx> { } } -// Returns from the enclosing function if the type metadata with the given -// unique id can be found in the type map +/// Returns from the enclosing function if the type metadata with the given +/// unique ID can be found in the type map. macro_rules! return_if_metadata_created_in_meantime { ($cx: expr, $unique_type_id: expr) => ( if let Some(metadata) = debug_context($cx).type_map @@ -527,19 +530,19 @@ pub fn type_metadata( t: Ty<'tcx>, usage_site_span: Span, ) -> &'ll DIType { - // Get the unique type id of this type. + // Get the unique type ID of this type. let unique_type_id = { let mut type_map = debug_context(cx).type_map.borrow_mut(); - // First, try to find the type in TypeMap. If we have seen it before, we + // First, try to find the type in `TypeMap`. If we have seen it before, we // can exit early here. match type_map.find_metadata_for_type(t) { Some(metadata) => { return metadata; }, None => { - // The Ty is not in the TypeMap but maybe we have already seen + // The Ty is not in the `TypeMap` but maybe we have already seen // an equivalent type (e.g., only differing in region arguments). - // In order to find out, generate the unique type id and look + // In order to find out, generate the unique type ID and look // that up. let unique_type_id = type_map.get_unique_type_id_of_type(cx, t); match type_map.find_metadata_for_unique_id(unique_type_id) { @@ -647,15 +650,15 @@ pub fn type_metadata( // // fn foo() -> impl Copy { foo } // - // See TypeMap::remove_type for more detals - // about the workaround + // See `TypeMap::remove_type` for more detals + // about the workaround. let temp_type = { unsafe { // The choice of type here is pretty arbitrary - // anything reading the debuginfo for a recursive // type is going to see *somthing* weird - the only - // question is what exactly it will see + // question is what exactly it will see. let (size, align) = cx.size_and_align_of(t); llvm::LLVMRustDIBuilderCreateBasicType( DIB(cx), @@ -677,7 +680,7 @@ pub fn type_metadata( type_map.borrow_mut().remove_type(t); - // This is actually a function pointer, so wrap it in pointer DI + // This is actually a function pointer, so wrap it in pointer DI. MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false) } @@ -743,14 +746,14 @@ pub fn type_metadata( let mut type_map = debug_context(cx).type_map.borrow_mut(); if already_stored_in_typemap { - // Also make sure that we already have a TypeMap entry for the unique type id. + // Also make sure that we already have a `TypeMap` entry for the unique type ID. let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) { Some(metadata) => metadata, None => { span_bug!(usage_site_span, - "Expected type metadata for unique \ - type id '{}' to already be in \ - the debuginfo::TypeMap but it \ + "expected type metadata for unique \ + type ID '{}' to already be in \ + the `debuginfo::TypeMap` but it \ was not. (Ty = {})", type_map.get_unique_type_id_as_string(unique_type_id), t); @@ -761,9 +764,9 @@ pub fn type_metadata( Some(metadata) => { if metadata != metadata_for_uid { span_bug!(usage_site_span, - "Mismatch between Ty and \ - UniqueTypeId maps in \ - debuginfo::TypeMap. \ + "mismatch between `Ty` and \ + `UniqueTypeId` maps in \ + `debuginfo::TypeMap`. \ UniqueTypeId={}, Ty={}", type_map.get_unique_type_id_as_string(unique_type_id), t); @@ -843,15 +846,15 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_unsigned_char), ty::Int(int_ty) => { - (int_ty.ty_to_string(), DW_ATE_signed) + (int_ty.name_str(), DW_ATE_signed) }, ty::Uint(uint_ty) => { - (uint_ty.ty_to_string(), DW_ATE_unsigned) + (uint_ty.name_str(), DW_ATE_unsigned) }, ty::Float(float_ty) => { - (float_ty.ty_to_string(), DW_ATE_float) + (float_ty.name_str(), DW_ATE_float) }, - _ => bug!("debuginfo::basic_type_metadata - t is invalid type") + _ => bug!("debuginfo::basic_type_metadata - `t` is invalid type") }; let (size, align) = cx.size_and_align_of(t); @@ -908,7 +911,7 @@ pub fn compile_unit_metadata( }; // The OSX linker has an idiosyncrasy where it will ignore some debuginfo - // if multiple object files with the same DW_AT_name are linked together. + // if multiple object files with the same `DW_AT_name` are linked together. // As a workaround we generate unique names for each object file. Those do // not correspond to an actual source file but that should be harmless. if tcx.sess.target.target.options.is_like_osx { @@ -935,11 +938,9 @@ pub fn compile_unit_metadata( // // This should actually be // - // ``` - // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); - // ``` + // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); // - // that is, we should set LLVM's emission kind to `LineTablesOnly` if + // That is, we should set LLVM's emission kind to `LineTablesOnly` if // we are compiling with "limited" debuginfo. However, some of the // existing tools relied on slightly more debuginfo being generated than // would be the case with `LineTablesOnly`, and we did not want to break @@ -1029,8 +1030,8 @@ impl MetadataCreationResult<'ll> { } } -// Description of a type member, which can either be a regular field (as in -// structs or tuples) or an enum variant. +/// Description of a type member, which can either be a regular field (as in +/// structs or tuples) or an enum variant. #[derive(Debug)] struct MemberDescription<'ll> { name: String, @@ -1067,10 +1068,10 @@ impl<'ll> MemberDescription<'ll> { } } -// A factory for MemberDescriptions. It produces a list of member descriptions -// for some record-like type. MemberDescriptionFactories are used to defer the -// creation of type member descriptions in order to break cycles arising from -// recursive type definitions. +/// A factory for `MemberDescription`s. It produces a list of member descriptions +/// for some record-like type. `MemberDescriptionFactory`s are used to defer the +/// creation of type member descriptions in order to break cycles arising from +/// recursive type definitions. enum MemberDescriptionFactory<'ll, 'tcx> { StructMDF(StructMemberDescriptionFactory<'tcx>), TupleMDF(TupleMemberDescriptionFactory<'tcx>), @@ -1106,7 +1107,7 @@ impl MemberDescriptionFactory<'ll, 'tcx> { // Structs //=----------------------------------------------------------------------------- -// Creates MemberDescriptions for the fields of a struct +/// Creates `MemberDescription`s for the fields of a struct. struct StructMemberDescriptionFactory<'tcx> { ty: Ty<'tcx>, variant: &'tcx ty::VariantDef, @@ -1177,7 +1178,7 @@ fn prepare_struct_metadata( // Tuples //=----------------------------------------------------------------------------- -// Creates MemberDescriptions for the fields of a tuple +/// Creates `MemberDescription`s for the fields of a tuple. struct TupleMemberDescriptionFactory<'tcx> { ty: Ty<'tcx>, component_types: Vec>, @@ -1300,14 +1301,14 @@ fn prepare_union_metadata( // Enums //=----------------------------------------------------------------------------- -// DWARF variant support is only available starting in LLVM 8. -// Although the earlier enum debug info output did not work properly -// in all situations, it is better for the time being to continue to -// sometimes emit the old style rather than emit something completely -// useless when rust is compiled against LLVM 6 or older. LLVM 7 -// contains an early version of the DWARF variant support, and will -// crash when handling the new debug info format. This function -// decides which representation will be emitted. +/// DWARF variant support is only available starting in LLVM 8. +/// Although the earlier enum debug info output did not work properly +/// in all situations, it is better for the time being to continue to +/// sometimes emit the old style rather than emit something completely +/// useless when rust is compiled against LLVM 6 or older. LLVM 7 +/// contains an early version of the DWARF variant support, and will +/// crash when handling the new debug info format. This function +/// decides which representation will be emitted. fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { // On MSVC we have to use the fallback mode, because LLVM doesn't // lower variant parts to PDB. @@ -1318,11 +1319,50 @@ fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { || llvm_util::get_major_version() < 8; } -// Describes the members of an enum value: An enum is described as a union of -// structs in DWARF. This MemberDescriptionFactory provides the description for -// the members of this union; so for every variant of the given enum, this -// factory will produce one MemberDescription (all with no name and a fixed -// offset of zero bytes). +// FIXME(eddyb) maybe precompute this? Right now it's computed once +// per generator monomorphization, but it doesn't depend on substs. +fn generator_layout_and_saved_local_names( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> (&'tcx GeneratorLayout<'tcx>, IndexVec>) { + let body = tcx.optimized_mir(def_id); + let generator_layout = body.generator_layout.as_ref().unwrap(); + let mut generator_saved_local_names = + IndexVec::from_elem(None, &generator_layout.field_tys); + + let state_arg = mir::PlaceBase::Local(mir::Local::new(1)); + for var in &body.var_debug_info { + if var.place.base != state_arg { + continue; + } + match var.place.projection[..] { + [ + // Deref of the `Pin<&mut Self>` state argument. + mir::ProjectionElem::Field(..), + mir::ProjectionElem::Deref, + + // Field of a variant of the state. + mir::ProjectionElem::Downcast(_, variant), + mir::ProjectionElem::Field(field, _), + ] => { + let name = &mut generator_saved_local_names[ + generator_layout.variant_fields[variant][field] + ]; + if name.is_none() { + name.replace(var.name); + } + } + _ => {} + } + } + (generator_layout, generator_saved_local_names) +} + +/// Describes the members of an enum value; an enum is described as a union of +/// structs in DWARF. This `MemberDescriptionFactory` provides the description for +/// the members of this union; so for every variant of the given enum, this +/// factory will produce one `MemberDescription` (all with no name and a fixed +/// offset of zero bytes). struct EnumMemberDescriptionFactory<'ll, 'tcx> { enum_type: Ty<'tcx>, layout: TyLayout<'tcx>, @@ -1334,12 +1374,25 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> { impl EnumMemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { + let generator_variant_info_data = match self.enum_type.kind { + ty::Generator(def_id, ..) => { + Some(generator_layout_and_saved_local_names(cx.tcx, def_id)) + } + _ => None, + }; + let variant_info_for = |index: VariantIdx| { - match &self.enum_type.kind { + match self.enum_type.kind { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), - ty::Generator(def_id, substs, _) => { - let generator_layout = cx.tcx.generator_layout(*def_id); - VariantInfo::Generator(substs, generator_layout, index) + ty::Generator(_, substs, _) => { + let (generator_layout, generator_saved_local_names) = + generator_variant_info_data.as_ref().unwrap(); + VariantInfo::Generator { + substs, + generator_layout: *generator_layout, + generator_saved_local_names, + variant_index: index, + } } _ => bug!(), } @@ -1456,7 +1509,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } => { if fallback { let variant = self.layout.for_variant(cx, dataful_variant); - // Create a description of the non-null variant + // Create a description of the non-null variant. let (variant_type_metadata, member_description_factory) = describe_enum_variant(cx, variant, @@ -1566,9 +1619,9 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } } -// Creates MemberDescriptions for the fields of a single enum variant. +// Creates `MemberDescription`s for the fields of a single enum variant. struct VariantMemberDescriptionFactory<'ll, 'tcx> { - // Cloned from the layout::Struct describing the variant. + /// Cloned from the `layout::Struct` describing the variant. offsets: Vec, args: Vec<(String, Ty<'tcx>)>, discriminant_type_metadata: Option<&'ll DIType>, @@ -1610,16 +1663,21 @@ enum EnumDiscriminantInfo<'ll> { } #[derive(Copy, Clone)] -enum VariantInfo<'tcx> { +enum VariantInfo<'a, 'tcx> { Adt(&'tcx ty::VariantDef), - Generator(SubstsRef<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx), + Generator { + substs: SubstsRef<'tcx>, + generator_layout: &'tcx GeneratorLayout<'tcx>, + generator_saved_local_names: &'a IndexVec>, + variant_index: VariantIdx, + }, } -impl<'tcx> VariantInfo<'tcx> { +impl<'tcx> VariantInfo<'_, 'tcx> { fn map_struct_name(&self, f: impl FnOnce(&str) -> R) -> R { match self { VariantInfo::Adt(variant) => f(&variant.ident.as_str()), - VariantInfo::Generator(substs, _, variant_index) => + VariantInfo::Generator { substs, variant_index, .. } => f(&substs.as_generator().variant_name(*variant_index)), } } @@ -1627,7 +1685,7 @@ impl<'tcx> VariantInfo<'tcx> { fn variant_name(&self) -> String { match self { VariantInfo::Adt(variant) => variant.ident.to_string(), - VariantInfo::Generator(_, _, variant_index) => { + VariantInfo::Generator { variant_index, .. } => { // Since GDB currently prints out the raw discriminant along // with every variant, make each variant name be just the value // of the discriminant. The struct name for the variant includes @@ -1638,28 +1696,31 @@ impl<'tcx> VariantInfo<'tcx> { } fn field_name(&self, i: usize) -> String { - let field_name = match self { + let field_name = match *self { VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn => - Some(variant.fields[i].ident.to_string()), - VariantInfo::Generator(_, generator_layout, variant_index) => { - let field = generator_layout.variant_fields[*variant_index][i.into()]; - let decl = &generator_layout.__local_debuginfo_codegen_only_do_not_use[field]; - decl.name.map(|name| name.to_string()) - } + Some(variant.fields[i].ident.name), + VariantInfo::Generator { + generator_layout, + generator_saved_local_names, + variant_index, + .. + } => generator_saved_local_names[ + generator_layout.variant_fields[variant_index][i.into()] + ], _ => None, }; - field_name.unwrap_or_else(|| format!("__{}", i)) + field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i)) } } -// Returns a tuple of (1) type_metadata_stub of the variant, (2) a -// MemberDescriptionFactory for producing the descriptions of the -// fields of the variant. This is a rudimentary version of a full -// RecursiveTypeDescription. +/// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a +/// `MemberDescriptionFactory` for producing the descriptions of the +/// fields of the variant. This is a rudimentary version of a full +/// `RecursiveTypeDescription`. fn describe_enum_variant( cx: &CodegenCx<'ll, 'tcx>, layout: layout::TyLayout<'tcx>, - variant: VariantInfo<'tcx>, + variant: VariantInfo<'_, 'tcx>, discriminant_info: EnumDiscriminantInfo<'ll>, containing_scope: &'ll DIScope, span: Span, @@ -1904,8 +1965,8 @@ fn prepare_enum_metadata( let discr_type = match discr.value { layout::Int(t, _) => t, - layout::Float(layout::FloatTy::F32) => Integer::I32, - layout::Float(layout::FloatTy::F64) => Integer::I64, + layout::F32 => Integer::I32, + layout::F64 => Integer::I64, layout::Pointer => cx.data_layout().ptr_sized_integer(), }.to_ty(cx.tcx, false); @@ -2088,8 +2149,7 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>, } } -// Compute the type parameters for a type, if any, for the given -// metadata. +/// Computes the type parameters for a type, if any, for the given metadata. fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> { if let ty::Adt(def, substs) = ty.kind { if !substs.types().next().is_none() { @@ -2134,9 +2194,9 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&' } } -// A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do -// any caching, does not add any fields to the struct. This can be done later -// with set_members_of_composite_type(). +/// A convenience wrapper around `LLVMRustDIBuilderCreateStructType()`. Does not do +/// any caching, does not add any fields to the struct. This can be done later +/// with `set_members_of_composite_type()`. fn create_struct_stub( cx: &CodegenCx<'ll, 'tcx>, struct_type: Ty<'tcx>, @@ -2151,9 +2211,9 @@ fn create_struct_stub( debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) ); let metadata_stub = unsafe { - // LLVMRustDIBuilderCreateStructType() wants an empty array. A null + // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions - // later on in llvm/lib/IR/Value.cpp. + // later on in `llvm/lib/IR/Value.cpp`. let empty_array = create_DIArray(DIB(cx), &[]); llvm::LLVMRustDIBuilderCreateStructType( @@ -2189,9 +2249,9 @@ fn create_union_stub( debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id) ); let metadata_stub = unsafe { - // LLVMRustDIBuilderCreateUnionType() wants an empty array. A null + // `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions - // later on in llvm/lib/IR/Value.cpp. + // later on in `llvm/lib/IR/Value.cpp`. let empty_array = create_DIArray(DIB(cx), &[]); llvm::LLVMRustDIBuilderCreateUnionType( @@ -2231,8 +2291,8 @@ pub fn create_global_var_metadata( } let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE); - // We may want to remove the namespace scope if we're in an extern block, see: - // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952 + // We may want to remove the namespace scope if we're in an extern block (see + // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952). let var_scope = get_namespace_for_item(cx, def_id); let span = tcx.def_span(def_id); @@ -2287,14 +2347,14 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: & let type_metadata = type_metadata(cx, ty, syntax_pos::DUMMY_SP); unsafe { - // LLVMRustDIBuilderCreateStructType() wants an empty array. A null + // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions - // later on in llvm/lib/IR/Value.cpp. + // later on in `llvm/lib/IR/Value.cpp`. let empty_array = create_DIArray(DIB(cx), &[]); let name = const_cstr!("vtable"); - // Create a new one each time. We don't want metadata caching + // Create a new one each time. We don't want metadata caching // here, because each vtable will refer to a unique containing // type. let vtable_type = llvm::LLVMRustDIBuilderCreateStructType( @@ -2327,7 +2387,7 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: & } } -// Creates an "extension" of an existing DIScope into another file. +/// Creates an "extension" of an existing `DIScope` into another file. pub fn extend_scope_to_file( cx: &CodegenCx<'ll, '_>, scope_metadata: &'ll DIScope, diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 7713fe4700..1de298de75 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -16,7 +16,7 @@ use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::ty::subst::{SubstsRef, GenericArgKind}; -use crate::abi::Abi; +use crate::abi::FnAbi; use crate::common::CodegenCx; use crate::builder::Builder; use crate::value::Value; @@ -32,7 +32,8 @@ use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope, use libc::c_uint; use std::cell::RefCell; -use std::ffi::{CStr, CString}; +use std::ffi::CString; +use log::debug; use smallvec::SmallVec; use syntax_pos::{self, BytePos, Span, Pos}; @@ -255,23 +256,11 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } - let old_name = unsafe { - CStr::from_ptr(llvm::LLVMGetValueName(value)) - }; - match old_name.to_str() { - Ok("") => {} - Ok(_) => { - // Avoid replacing the name if it already exists. - // While we could combine the names somehow, it'd - // get noisy quick, and the usefulness is dubious. - return; - } - Err(_) => return, - } - - let cname = SmallCStr::new(name); - unsafe { - llvm::LLVMSetValueName(value, cname.as_ptr()); + // Avoid replacing the name if it already exists. + // While we could combine the names somehow, it'd + // get noisy quick, and the usefulness is dubious. + if llvm::get_value_name(value).is_empty() { + llvm::set_value_name(value, name.as_bytes()); } } } @@ -280,7 +269,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn create_function_debug_context( &self, instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: &'ll Value, mir: &mir::Body<'_>, ) -> Option> { @@ -308,7 +297,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let file_metadata = file_metadata(self, &loc.file.name, def_id.krate); let function_type_metadata = unsafe { - let fn_signature = get_function_signature(self, sig); + let fn_signature = get_function_signature(self, fn_abi); llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature) }; @@ -338,7 +327,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let mut flags = DIFlags::FlagPrototyped; - if self.layout_of(sig.output()).abi.is_uninhabited() { + if fn_abi.ret.layout.abi.is_uninhabited() { flags |= DIFlags::FlagNoReturn; } @@ -392,25 +381,20 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn get_function_signature<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - sig: ty::FnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> &'ll DIArray { if cx.sess().opts.debuginfo == DebugInfo::Limited { return create_DIArray(DIB(cx), &[]); } - let mut signature = Vec::with_capacity(sig.inputs().len() + 1); + let mut signature = Vec::with_capacity(fn_abi.args.len() + 1); // Return type -- llvm::DIBuilder wants this at index 0 - signature.push(match sig.output().kind { - ty::Tuple(ref tys) if tys.is_empty() => None, - _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)) - }); - - let inputs = if sig.abi == Abi::RustCall { - &sig.inputs()[..sig.inputs().len() - 1] + signature.push(if fn_abi.ret.is_ignore() { + None } else { - sig.inputs() - }; + Some(type_metadata(cx, fn_abi.ret.layout.ty, syntax_pos::DUMMY_SP)) + }); // Arguments types if cx.sess().target.target.options.is_like_msvc { @@ -424,7 +408,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`. // This transformed type is wrong, but these function types are // already inaccurate due to ABI adjustments (see #42800). - signature.extend(inputs.iter().map(|&t| { + signature.extend(fn_abi.args.iter().map(|arg| { + let t = arg.layout.ty; let t = match t.kind { ty::Array(ct, _) if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => { @@ -435,21 +420,11 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) })); } else { - signature.extend(inputs.iter().map(|t| { - Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) + signature.extend(fn_abi.args.iter().map(|arg| { + Some(type_metadata(cx, arg.layout.ty, syntax_pos::DUMMY_SP)) })); } - if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { - if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].kind { - signature.extend( - args.iter().map(|argument_type| { - Some(type_metadata(cx, argument_type.expect_ty(), syntax_pos::DUMMY_SP)) - }) - ); - } - } - create_DIArray(DIB(cx), &signature[..]) } diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 628d1372b5..482bcf2aa5 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -34,11 +34,11 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { }); let namespace_name = match def_key.disambiguated_data.data { - DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(), - data => data.as_symbol().as_str() + DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate), + data => data.as_symbol() }; - let namespace_name = SmallCStr::new(&namespace_name); + let namespace_name = SmallCStr::new(&namespace_name.as_str()); let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs index ccb3bde1cb..82183fa9bd 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -8,6 +8,7 @@ use crate::llvm; use crate::llvm::debuginfo::DIScope; use crate::builder::Builder; use rustc_codegen_ssa::traits::*; +use log::debug; use libc::c_uint; use syntax_pos::{Span, Pos}; diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 62eab0f3d4..5144b92ea1 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -13,16 +13,16 @@ use crate::llvm; use crate::llvm::AttributePlace::Function; -use crate::abi::{FnType, FnTypeLlvmExt}; +use crate::abi::{FnAbi, FnAbiLlvmExt}; use crate::attributes; use crate::context::CodegenCx; use crate::type_::Type; use crate::value::Value; -use rustc::ty::{self, PolyFnSig}; -use rustc::ty::layout::{FnTypeExt, LayoutOf}; +use rustc::ty::Ty; use rustc::session::config::Sanitizer; use rustc_data_structures::small_c_str::SmallCStr; use rustc_codegen_ssa::traits::*; +use log::debug; /// Declare a function. /// @@ -77,9 +77,8 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { name: &str, ty: &'ll Type ) -> &'ll Value { debug!("declare_global(name={:?})", name); - let namebuf = SmallCStr::new(name); unsafe { - llvm::LLVMRustGetOrInsertGlobal(self.llmod, namebuf.as_ptr(), ty) + llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) } } @@ -94,21 +93,12 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn declare_fn( &self, name: &str, - sig: PolyFnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> &'ll Value { - debug!("declare_rust_fn(name={:?}, sig={:?})", name, sig); - let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - debug!("declare_rust_fn (after region erasure) sig={:?}", sig); - - let fty = FnType::new(self, sig, &[]); - let llfn = declare_raw_fn(self, name, fty.llvm_cconv(), fty.llvm_type(self)); - - if self.layout_of(sig.output()).abi.is_uninhabited() { - llvm::Attribute::NoReturn.apply_llfn(Function, llfn); - } - - fty.apply_attrs_llfn(self, llfn); + debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi); + let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self)); + fn_abi.apply_attrs_llfn(self, llfn); llfn } @@ -130,28 +120,6 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } - fn define_fn( - &self, - name: &str, - fn_sig: PolyFnSig<'tcx>, - ) -> &'ll Value { - if self.get_defined_value(name).is_some() { - self.sess().fatal(&format!("symbol `{}` already defined", name)) - } else { - self.declare_fn(name, fn_sig) - } - } - - fn define_internal_fn( - &self, - name: &str, - fn_sig: PolyFnSig<'tcx>, - ) -> &'ll Value { - let llfn = self.define_fn(name, fn_sig); - unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; - llfn - } - fn get_declared_value(&self, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); let namebuf = SmallCStr::new(name); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 02424956b9..900f2d2def 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1,7 +1,6 @@ -use crate::attributes; use crate::llvm; use crate::llvm_util; -use crate::abi::{Abi, FnType, LlvmType, PassMode}; +use crate::abi::{Abi, FnAbi, LlvmType, PassMode}; use crate::context::CodegenCx; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; @@ -14,12 +13,13 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::glue; use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types}; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; +use rustc::ty::layout::{self, FnAbiExt, LayoutOf, HasTyCtxt, Primitive}; use rustc::mir::interpret::GlobalId; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; -use syntax::ast::{self, FloatTy}; use rustc_target::abi::HasDataLayout; +use syntax::ast; +use rustc::{bug, span_bug}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::traits::*; @@ -84,7 +84,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn codegen_intrinsic_call( &mut self, instance: ty::Instance<'tcx>, - fn_ty: &FnType<'tcx, Ty<'tcx>>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, &'ll Value>], llresult: &'ll Value, span: Span, @@ -104,7 +104,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let name = &*tcx.item_name(def_id).as_str(); let llret_ty = self.layout_of(ret_ty).llvm_type(self); - let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout); + let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); let simple = get_simple_intrinsic(self, name); let llval = match name { @@ -147,12 +147,12 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.call(intrinsic, &[args[0].immediate(), args[1].immediate()], None) } "va_arg" => { - match fn_ty.ret.layout.abi { + match fn_abi.ret.layout.abi { layout::Abi::Scalar(ref scalar) => { match scalar.value { Primitive::Int(..) => { if self.cx().size_of(ret_ty).bytes() < 4 { - // va_arg should not be called on a integer type + // `va_arg` should not be called on a integer type // less than 4 bytes in length. If it is, promote // the integer to a `i32` and truncate the result // back to the smaller type. @@ -163,12 +163,12 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { emit_va_arg(self, args[0], ret_ty) } } - Primitive::Float(FloatTy::F64) | + Primitive::F64 | Primitive::Pointer => { emit_va_arg(self, args[0], ret_ty) } // `va_arg` should never be used with the return type f32. - Primitive::Float(FloatTy::F32) => { + Primitive::F32 => { bug!("the va_arg intrinsic does not work with `f32`") } } @@ -276,7 +276,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { "volatile_load" | "unaligned_volatile_load" => { let tp_ty = substs.type_at(0); let mut ptr = args[0].immediate(); - if let PassMode::Cast(ty) = fn_ty.ret.mode { + if let PassMode::Cast(ty) = fn_abi.ret.mode { ptr = self.pointercast(ptr, self.type_ptr_to(ty.llvm_type(self))); } let load = self.volatile_load(ptr); @@ -442,32 +442,11 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let is_left = name == "rotate_left"; let val = args[0].immediate(); let raw_shift = args[1].immediate(); - if llvm_util::get_major_version() >= 7 { - // rotate = funnel shift with first two args the same - let llvm_name = &format!("llvm.fsh{}.i{}", - if is_left { 'l' } else { 'r' }, width); - let llfn = self.get_intrinsic(llvm_name); - self.call(llfn, &[val, val, raw_shift], None) - } else { - // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW)) - // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW)) - let width = self.const_uint( - self.type_ix(width), - width, - ); - let shift = self.urem(raw_shift, width); - let width_minus_raw_shift = self.sub(width, raw_shift); - let inv_shift = self.urem(width_minus_raw_shift, width); - let shift1 = self.shl( - val, - if is_left { shift } else { inv_shift }, - ); - let shift2 = self.lshr( - val, - if !is_left { shift } else { inv_shift }, - ); - self.or(shift1, shift2) - } + // rotate = funnel shift with first two args the same + let llvm_name = &format!("llvm.fsh{}.i{}", + if is_left { 'l' } else { 'r' }, width); + let llfn = self.get_intrinsic(llvm_name); + self.call(llfn, &[val, val, raw_shift], None) }, "saturating_add" | "saturating_sub" => { let is_add = name == "saturating_add"; @@ -538,9 +517,36 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } } - }, + "float_to_int_approx_unchecked" => { + if float_type_width(arg_tys[0]).is_none() { + span_invalid_monomorphization_error( + tcx.sess, span, + &format!("invalid monomorphization of `float_to_int_approx_unchecked` \ + intrinsic: expected basic float type, \ + found `{}`", arg_tys[0])); + return; + } + match int_type_width_signed(ret_ty, self.cx) { + Some((width, signed)) => { + if signed { + self.fptosi(args[0].immediate(), self.cx.type_ix(width)) + } else { + self.fptoui(args[0].immediate(), self.cx.type_ix(width)) + } + } + None => { + span_invalid_monomorphization_error( + tcx.sess, span, + &format!("invalid monomorphization of `float_to_int_approx_unchecked` \ + intrinsic: expected basic integer type, \ + found `{}`", ret_ty)); + return; + } + } + } + "discriminant_value" => { args[0].deref(self.cx()).codegen_get_discr(self, ret_ty) } @@ -715,8 +721,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { _ => bug!("unknown intrinsic '{}'", name), }; - if !fn_ty.ret.is_ignore() { - if let PassMode::Cast(ty) = fn_ty.ret.mode { + if !fn_abi.ret.is_ignore() { + if let PassMode::Cast(ty) = fn_abi.ret.mode { let ptr_llty = self.type_ptr_to(ty.llvm_type(self)); let ptr = self.pointercast(result.llval, ptr_llty); self.store(llval, ptr, result.align); @@ -1013,8 +1019,10 @@ fn gen_fn<'ll, 'tcx>( hir::Unsafety::Unsafe, Abi::Rust )); - let llfn = cx.define_internal_fn(name, rust_fn_sig); - attributes::from_fn_attrs(cx, llfn, None, rust_fn_sig); + let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); + let llfn = cx.declare_fn(name, &fn_abi); + // FIXME(eddyb) find a nicer way to do this. + unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; let bx = Builder::new_block(cx, llfn, "entry-block"); codegen(bx); llfn @@ -1105,8 +1113,8 @@ fn generic_simd_intrinsic( 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(), + ty::Int(i) => i.bit_width().unwrap() as u64, + ty::Uint(i) => i.bit_width().unwrap() as u64, _ => return_error!("`{}` is not an integral type", in_ty), }; require_simd!(arg_tys[1], "argument"); @@ -1116,7 +1124,7 @@ fn generic_simd_intrinsic( m_len, v_len ); let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, m_len as u64); + let i1xn = bx.type_vector(i1, m_len); let m_i1s = bx.bitcast(args[0].immediate(), i1xn); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } @@ -1160,7 +1168,7 @@ fn generic_simd_intrinsic( } if name.starts_with("simd_shuffle") { - let n: usize = name["simd_shuffle".len()..].parse().unwrap_or_else(|_| + let n: u64 = name["simd_shuffle".len()..].parse().unwrap_or_else(|_| span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")); require_simd!(ret_ty, "return"); @@ -1175,7 +1183,7 @@ fn generic_simd_intrinsic( in_elem, in_ty, ret_ty, ret_ty.simd_type(tcx)); - let total_len = in_len as u128 * 2; + let total_len = u128::from(in_len) * 2; let vector = args[2].immediate(); @@ -1251,7 +1259,7 @@ fn generic_simd_intrinsic( // trailing bits. let expected_int_bits = in_len.max(8); match ret_ty.kind { - ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (), + ty::Uint(i) if i.bit_width() == Some(expected_int_bits as usize) => (), _ => return_error!( "bitmask `{}`, expected `u{}`", ret_ty, expected_int_bits @@ -1276,7 +1284,8 @@ fn generic_simd_intrinsic( // Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position. let shift_indices = vec![ - bx.cx.const_int(bx.type_ix(in_elem_bitwidth as _), (in_elem_bitwidth - 1) as _); in_len + bx.cx.const_int(bx.type_ix(in_elem_bitwidth as _), (in_elem_bitwidth - 1) as _); + in_len as _ ]; let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice())); // Truncate vector to an @@ -1291,7 +1300,7 @@ fn generic_simd_intrinsic( name: &str, in_elem: &::rustc::ty::TyS<'_>, in_ty: &::rustc::ty::TyS<'_>, - in_len: usize, + in_len: u64, bx: &mut Builder<'a, 'll, 'tcx>, span: Span, args: &[OperandRef<'tcx, &'ll Value>], @@ -1335,7 +1344,7 @@ fn generic_simd_intrinsic( }, ty::Float(f) => { return_error!("unsupported element type `{}` of floating-point vector `{}`", - f, in_ty); + f.name_str(), in_ty); }, _ => { return_error!("`{}` is not a floating-point type", in_ty); @@ -1400,7 +1409,7 @@ fn generic_simd_intrinsic( // FIXME: use: // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Function.h#L182 // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81 - fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: usize, no_pointers: usize) -> String { + fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: u64, no_pointers: usize) -> String { let p0s: String = "p0".repeat(no_pointers); match elem_ty.kind { ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), @@ -1410,7 +1419,7 @@ fn generic_simd_intrinsic( } } - fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: Ty<'_>, vec_len: usize, + fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: Ty<'_>, vec_len: u64, mut no_pointers: usize) -> &'ll Type { // FIXME: use cx.layout_of(ty).llvm_type() ? let mut elem_ty = match elem_ty.kind { @@ -1423,7 +1432,7 @@ fn generic_simd_intrinsic( elem_ty = cx.type_ptr_to(elem_ty); no_pointers -= 1; } - cx.type_vector(elem_ty, vec_len as u64) + cx.type_vector(elem_ty, vec_len) } @@ -1506,7 +1515,7 @@ fn generic_simd_intrinsic( // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, in_len as u64); + let i1xn = bx.type_vector(i1, in_len); (bx.trunc(args[2].immediate(), i1xn), i1xn) }; @@ -1573,7 +1582,7 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind { - ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::MutMutable + ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mutable => (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))), _ => { @@ -1606,7 +1615,7 @@ fn generic_simd_intrinsic( // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, in_len as u64); + let i1xn = bx.type_vector(i1, in_len); (bx.trunc(args[2].immediate(), i1xn), i1xn) }; @@ -1925,7 +1934,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, bool)> { match ty.kind { ty::Int(t) => Some((match t { - ast::IntTy::Isize => cx.tcx.sess.target.isize_ty.bit_width().unwrap() as u64, + ast::IntTy::Isize => cx.tcx.sess.target.ptr_width as u64, ast::IntTy::I8 => 8, ast::IntTy::I16 => 16, ast::IntTy::I32 => 32, @@ -1933,7 +1942,7 @@ fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, boo ast::IntTy::I128 => 128, }, true)), ty::Uint(t) => Some((match t { - ast::UintTy::Usize => cx.tcx.sess.target.usize_ty.bit_width().unwrap() as u64, + ast::UintTy::Usize => cx.tcx.sess.target.ptr_width as u64, ast::UintTy::U8 => 8, ast::UintTy::U16 => 16, ast::UintTy::U32 => 32, diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index e7562c399b..1e1d74cfa9 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(const_cstr_unchecked)] @@ -23,31 +24,11 @@ use back::write::{create_target_machine, create_informational_target_machine}; use syntax_pos::symbol::Symbol; -extern crate rustc_demangle; -extern crate flate2; -#[macro_use] extern crate bitflags; -extern crate libc; -#[macro_use] extern crate rustc; -extern crate rustc_target; -#[macro_use] extern crate rustc_data_structures; -extern crate rustc_index; -extern crate rustc_incremental; -extern crate rustc_codegen_utils; -extern crate rustc_codegen_ssa; -extern crate rustc_fs_util; -extern crate rustc_driver as _; - -#[macro_use] extern crate log; -extern crate smallvec; -extern crate syntax; -extern crate syntax_pos; -extern crate rustc_errors as errors; - use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, FatLTOInput}; use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModule}; use rustc_codegen_ssa::CompiledModule; -use errors::{FatalError, Handler}; +use rustc_errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; use syntax::expand::allocator::AllocatorKind; pub use llvm_util::target_features; @@ -336,12 +317,6 @@ impl CodegenBackend for LlvmCodegenBackend { } } -/// This is the entrypoint for a hot plugged rustc_codegen_llvm -#[no_mangle] -pub fn __rustc_codegen_backend() -> Box { - LlvmCodegenBackend::new() -} - pub struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index c69942ef3f..b8a1003b11 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -544,6 +544,7 @@ pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_voi pub mod debuginfo { use super::{InvariantOpaque, Metadata}; + use bitflags::bitflags; #[repr(C)] pub struct DIBuilder<'a>(InvariantOpaque<'a>); @@ -701,8 +702,8 @@ extern "C" { // Operations on all values pub fn LLVMTypeOf(Val: &Value) -> &Type; - pub fn LLVMGetValueName(Val: &Value) -> *const c_char; - pub fn LLVMSetValueName(Val: &Value, Name: *const c_char); + pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char; + pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t); pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value); pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value); @@ -774,7 +775,8 @@ extern "C" { pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>; pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>; - pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value; + pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, NameLen: size_t, + T: &'a Type) -> &'a Value; pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value; pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>; pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>; @@ -1341,6 +1343,8 @@ extern "C" { pub fn LLVMInitializePasses(); + pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>); + pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: &PassManagerBuilder, Value: Bool); @@ -1670,6 +1674,11 @@ extern "C" { pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; + pub fn LLVMRustCreateAddressSanitizerFunctionPass(Recover: bool) -> &'static mut Pass; + pub fn LLVMRustCreateModuleAddressSanitizerPass(Recover: bool) -> &'static mut Pass; + pub fn LLVMRustCreateMemorySanitizerPass(TrackOrigins: c_int, + Recover: bool) -> &'static mut Pass; + pub fn LLVMRustCreateThreadSanitizerPass() -> &'static mut Pass; pub fn LLVMRustAddPass(PM: &PassManager<'_>, Pass: &'static mut Pass); pub fn LLVMRustAddLastExtensionPasses(PMB: &PassManagerBuilder, Passes: *const &'static mut Pass, @@ -1684,6 +1693,7 @@ extern "C" { pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, CPU: *const c_char, Features: *const c_char, + Abi: *const c_char, Model: CodeModel, Reloc: RelocMode, Level: CodeGenOptLevel, @@ -1694,10 +1704,10 @@ extern "C" { TrapUnreachable: bool, Singlethread: bool, AsmComments: bool, - EmitStackSizeSection: bool) + EmitStackSizeSection: bool, + RelaxELFRelocations: bool) -> Option<&'static mut TargetMachine>; pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); - pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module); pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder, M: &'a Module, DisableSimplifyLibCalls: bool); @@ -1719,8 +1729,7 @@ extern "C" { Output: *const c_char, FileType: FileType) -> LLVMRustResult; - pub fn LLVMRustPrintModule(PM: &PassManager<'a>, - M: &'a Module, + pub fn LLVMRustPrintModule(M: &'a Module, Output: *const c_char, Demangle: extern fn(*const c_char, size_t, @@ -1729,6 +1738,7 @@ extern "C" { ) -> LLVMRustResult; pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); + pub fn LLVMRustGetInstructionCount(M: &Module) -> u32; pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool); pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); @@ -1803,8 +1813,9 @@ extern "C" { pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock); - pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char); + pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); pub fn LLVMRustUnsetComdat(V: &Value); + pub fn LLVMRustSetModulePICLevel(M: &Module); pub fn LLVMRustSetModulePIELevel(M: &Module); pub fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer; pub fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8; diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index 57815933af..975756753d 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -10,11 +10,11 @@ pub use self::Linkage::*; use std::str::FromStr; use std::string::FromUtf8Error; -use std::slice; use std::ffi::CStr; use std::cell::RefCell; -use libc::{c_uint, c_char, size_t}; +use libc::c_uint; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_llvm::RustString; pub mod archive_ro; pub mod diagnostic; @@ -81,21 +81,6 @@ impl FromStr for ArchiveKind { } } -#[repr(C)] -pub struct RustString { - bytes: RefCell>, -} - -/// Appending to a Rust string -- used by RawRustStringOstream. -#[no_mangle] -pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString, - ptr: *const c_char, - size: size_t) { - let slice = slice::from_raw_parts(ptr as *const u8, size as usize); - - sr.bytes.borrow_mut().extend_from_slice(slice); -} - pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) { unsafe { LLVMSetInstructionCallConv(instr, cc as c_uint); @@ -115,7 +100,8 @@ pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { // For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { unsafe { - LLVMRustSetComdat(llmod, val, LLVMGetValueName(val)); + let name = get_value_name(val); + LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len()); } } @@ -217,6 +203,23 @@ pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value { } } +/// Safe wrapper for `LLVMGetValueName2` into a byte slice +pub fn get_value_name(value: &'a Value) -> &'a [u8] { + unsafe { + let mut len = 0; + let data = LLVMGetValueName2(value, &mut len); + std::slice::from_raw_parts(data.cast(), len) + } +} + +/// Safe wrapper for `LLVMSetValueName2` from a byte slice +pub fn set_value_name(value: &Value, name: &[u8]) { + unsafe { + let data = name.as_ptr().cast(); + LLVMSetValueName2(value, data, name.len()); + } +} + pub fn build_string(f: impl FnOnce(&RustString)) -> Result { let sr = RustString { bytes: RefCell::new(Vec::new()), diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 85e0b6d465..40739387b0 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -6,8 +6,9 @@ use rustc::session::config::PrintRequest; use rustc_target::spec::{MergeFunctions, PanicStrategy}; use libc::c_int; use std::ffi::CString; -use syntax::feature_gate::UnstableFeatures; +use rustc_feature::UnstableFeatures; use syntax::symbol::sym; +use rustc::bug; use std::str; use std::slice; @@ -62,6 +63,9 @@ unsafe fn configure_llvm(sess: &Session) { if sess.opts.debugging_opts.disable_instrumentation_preinliner { add("-disable-preinline"); } + if sess.opts.debugging_opts.generate_arange_section { + add("-generate-arange-section"); + } if get_major_version() >= 8 { match sess.opts.debugging_opts.merge_functions .unwrap_or(sess.target.target.options.merge_functions) { @@ -105,6 +109,8 @@ const ARM_WHITELIST: &[(&str, Option)] = &[ ("rclass", Some(sym::arm_target_feature)), ("dsp", Some(sym::arm_target_feature)), ("neon", Some(sym::arm_target_feature)), + ("crc", Some(sym::arm_target_feature)), + ("crypto", Some(sym::arm_target_feature)), ("v5te", Some(sym::arm_target_feature)), ("v6", Some(sym::arm_target_feature)), ("v6k", Some(sym::arm_target_feature)), diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index cd72558881..bbe42e3b50 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -6,6 +6,8 @@ use rustc_target::spec::Target; use rustc_data_structures::owning_ref::OwningRef; use rustc_codegen_ssa::METADATA_FILENAME; +use log::debug; +use rustc_data_structures::rustc_erase_owner; use std::path::Path; use std::slice; diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index c1703ffd0c..9f6bdd2390 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -1,3 +1,4 @@ +use crate::abi::FnAbi; use crate::attributes; use crate::base; use crate::context::CodegenCx; @@ -6,8 +7,9 @@ use crate::type_of::LayoutLlvmExt; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty::{TypeFoldable, Instance}; -use rustc::ty::layout::{LayoutOf, HasTyCtxt}; +use rustc::ty::layout::{FnAbiExt, LayoutOf}; use rustc_codegen_ssa::traits::*; +use log::debug; pub use rustc::mir::mono::MonoItem; @@ -42,10 +44,10 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { assert!(!instance.substs.needs_infer() && !instance.substs.has_param_types()); - let mono_sig = instance.fn_sig(self.tcx()); - let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - let lldecl = self.declare_fn(symbol_name, mono_sig); + let fn_abi = FnAbi::of_instance(self, instance, &[]); + let lldecl = self.declare_fn(symbol_name, &fn_abi); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; + let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); base::set_link_section(lldecl, &attrs); if linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR { @@ -67,16 +69,9 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } - debug!("predefine_fn: mono_sig = {:?} instance = {:?}", mono_sig, instance); - if instance.def.is_inline(self.tcx) { - attributes::inline(self, lldecl, attributes::InlineAttr::Hint); - } - attributes::from_fn_attrs( - self, - lldecl, - Some(instance.def.def_id()), - mono_sig, - ); + debug!("predefine_fn: instance = {:?}", instance); + + attributes::from_fn_attrs(self, lldecl, instance, &fn_abi); self.instances.borrow_mut().insert(instance, lldecl); } diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index 8d6cd0bcf4..e6677f3d25 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -5,14 +5,15 @@ use crate::llvm::{Bool, False, True}; use crate::context::CodegenCx; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use rustc::bug; use crate::common; use crate::type_of::LayoutLlvmExt; -use crate::abi::{LlvmType, FnTypeLlvmExt}; +use crate::abi::{LlvmType, FnAbiLlvmExt}; use syntax::ast; use rustc::ty::Ty; use rustc::ty::layout::{self, Align, Size, TyLayout}; -use rustc_target::abi::call::{CastTarget, FnType, Reg}; +use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_codegen_ssa::common::TypeKind; @@ -243,7 +244,7 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type { assert_ne!(self.type_kind(ty), TypeKind::Function, - "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead"); + "don't call ptr_to on function types, use ptr_to_llvm_type on FnAbi instead"); ty.ptr_to() } @@ -336,8 +337,8 @@ impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn cast_backend_type(&self, ty: &CastTarget) -> &'ll Type { ty.llvm_type(self) } - fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type { - ty.ptr_to_llvm_type(self) + fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type { + fn_abi.ptr_to_llvm_type(self) } fn reg_backend_type(&self, ty: &Reg) -> &'ll Type { ty.llvm_type(self) diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index d921bbc96a..f9cbf4bbe4 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -1,11 +1,13 @@ -use crate::abi::{FnType}; +use crate::abi::{FnAbi}; use crate::common::*; use crate::type_::Type; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::layout::{self, Align, LayoutOf, FnTypeExt, PointeeInfo, Size, TyLayout}; -use rustc_target::abi::{FloatTy, TyLayoutMethods}; +use rustc::ty::layout::{self, Align, LayoutOf, FnAbiExt, PointeeInfo, Size, TyLayout}; +use rustc_target::abi::TyLayoutMethods; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc_codegen_ssa::traits::*; +use log::debug; +use rustc::bug; use std::fmt::Write; @@ -235,11 +237,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) } ty::FnPtr(sig) => { - let sig = cx.tcx.normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - cx.fn_ptr_backend_type(&FnType::new(cx, sig, &[])) + cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])) } _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO) }; @@ -300,8 +298,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { scalar: &layout::Scalar, offset: Size) -> &'a Type { match scalar.value { layout::Int(i, _) => cx.type_from_integer( i), - layout::Float(FloatTy::F32) => cx.type_f32(), - layout::Float(FloatTy::F64) => cx.type_f64(), + layout::F32 => cx.type_f32(), + layout::F64 => cx.type_f64(), layout::Pointer => { // If we know the alignment, pick something better than i8. let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) { diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 2eaae50591..d489852a1a 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -13,7 +13,7 @@ test = false bitflags = "1.2.1" cc = "1.0.1" num_cpus = "1.0" -memmap = "0.6" +memmap = "0.7" log = "0.4.5" libc = "0.2.44" jobserver = "0.1.11" @@ -31,3 +31,5 @@ rustc_fs_util = { path = "../librustc_fs_util" } rustc_incremental = { path = "../librustc_incremental" } rustc_index = { path = "../librustc_index" } rustc_target = { path = "../librustc_target" } +rustc_error_codes = { path = "../librustc_error_codes" } +rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs index 2d84d67e3c..b8501f0e12 100644 --- a/src/librustc_codegen_ssa/back/command.rs +++ b/src/librustc_codegen_ssa/back/command.rs @@ -53,7 +53,7 @@ impl Command { } pub fn sym_arg(&mut self, arg: Symbol) -> &mut Command { - self.arg(&arg.as_str()); + self.arg(&*arg.as_str()); self } diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 999cc40658..4278852123 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -398,7 +398,8 @@ impl<'a> Linker for GccLinker<'a> { fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { // Symbol visibility in object files typically takes care of this. - if crate_type == CrateType::Executable { + if crate_type == CrateType::Executable && + self.sess.target.target.options.override_export_symbols.is_none() { return; } diff --git a/src/librustc_codegen_ssa/back/rpath.rs b/src/librustc_codegen_ssa/back/rpath.rs index e27cb6d8dd..cd3d99951e 100644 --- a/src/librustc_codegen_ssa/back/rpath.rs +++ b/src/librustc_codegen_ssa/back/rpath.rs @@ -119,11 +119,7 @@ fn path_relative_from(path: &Path, base: &Path) -> Option { use std::path::Component; if path.is_absolute() != base.is_absolute() { - if path.is_absolute() { - Some(PathBuf::from(path)) - } else { - None - } + path.is_absolute().then(|| PathBuf::from(path)) } else { let mut ita = path.components(); let mut itb = base.components(); diff --git a/src/librustc_codegen_ssa/back/rpath/tests.rs b/src/librustc_codegen_ssa/back/rpath/tests.rs index e42a878d7e..e8457fe0e1 100644 --- a/src/librustc_codegen_ssa/back/rpath/tests.rs +++ b/src/librustc_codegen_ssa/back/rpath/tests.rs @@ -52,7 +52,7 @@ fn test_minimize2() { fn test_rpath_relative() { if cfg!(target_os = "macos") { let config = &mut RPathConfig { - used_crates: Vec::new(), + used_crates: &[], has_rpath: true, is_like_osx: true, linker_is_gnu: false, @@ -64,7 +64,7 @@ fn test_rpath_relative() { assert_eq!(res, "@loader_path/../lib"); } else { let config = &mut RPathConfig { - used_crates: Vec::new(), + used_crates: &[], out_filename: PathBuf::from("bin/rustc"), get_install_prefix_lib_path: &mut || panic!(), has_rpath: true, diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 85a90459f5..cea5dc18c1 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -85,11 +85,7 @@ fn reachable_non_generics_provider( match tcx.hir().get(hir_id) { Node::ForeignItem(..) => { let def_id = tcx.hir().local_def_id(hir_id); - if tcx.is_statically_included_foreign_item(def_id) { - Some(def_id) - } else { - None - } + tcx.is_statically_included_foreign_item(def_id).then_some(def_id) } // Only consider nodes that actually have exported symbols. @@ -129,9 +125,9 @@ fn reachable_non_generics_provider( // // In general though we won't link right if these // symbols are stripped, and LTO currently strips them. - if &*name == "rust_eh_personality" || - &*name == "rust_eh_register_frames" || - &*name == "rust_eh_unregister_frames" { + if name == "rust_eh_personality" || + name == "rust_eh_register_frames" || + name == "rust_eh_unregister_frames" { SymbolExportLevel::C } else { SymbolExportLevel::Rust @@ -194,7 +190,7 @@ fn exported_symbols_provider_local( symbols.push((exported_symbol, SymbolExportLevel::C)); } - if tcx.sess.allocator_kind.get().is_some() { + if tcx.allocator_kind().is_some() { for method in ALLOCATOR_METHODS { let symbol_name = format!("__rust_{}", method.name); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index b302b9ae7f..283295cadf 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -10,7 +10,7 @@ use crate::traits::*; use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess}; use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind}; -use rustc::dep_graph::cgu_reuse_tracker::CguReuseTracker; +use rustc_session::cgu_reuse_tracker::CguReuseTracker; use rustc::middle::cstore::EncodedMetadata; use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Lto, Sanitizer, SwitchWithOptPath}; @@ -19,11 +19,12 @@ use rustc::util::nodemap::FxHashMap; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::ty::TyCtxt; use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry}; -use rustc::util::profiling::SelfProfilerRef; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_fs_util::link_or_copy; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Handler, Level, FatalError, DiagnosticId, SourceMapperDyn}; +use rustc_errors::{Handler, Level, FatalError, DiagnosticId}; +use syntax_pos::source_map::SourceMap; use rustc_errors::emitter::{Emitter}; use rustc_target::spec::MergeFunctions; use syntax::attr; @@ -58,6 +59,10 @@ pub struct ModuleConfig { pub pgo_gen: SwitchWithOptPath, pub pgo_use: Option, + pub sanitizer: Option, + pub sanitizer_recover: Vec, + pub sanitizer_memory_track_origins: usize, + // Flags indicating which outputs to produce. pub emit_pre_lto_bc: bool, pub emit_no_opt_bc: bool, @@ -96,6 +101,10 @@ impl ModuleConfig { pgo_gen: SwitchWithOptPath::Disabled, pgo_use: None, + sanitizer: None, + sanitizer_recover: Default::default(), + sanitizer_memory_track_origins: 0, + emit_no_opt_bc: false, emit_pre_lto_bc: false, emit_bc: false, @@ -222,8 +231,6 @@ pub struct CodegenContext { pub total_cgus: usize, // Handler to use for diagnostics produced during codegen. pub diag_emitter: SharedEmitter, - // LLVM passes added by plugins. - pub plugin_passes: Vec, // LLVM optimizations for which we want to print remarks. pub remark: Passes, // Worker thread number @@ -344,29 +351,16 @@ pub fn start_async_codegen( let mut metadata_config = ModuleConfig::new(vec![]); let mut allocator_config = ModuleConfig::new(vec![]); - if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer { - match *sanitizer { - Sanitizer::Address => { - modules_config.passes.push("asan".to_owned()); - modules_config.passes.push("asan-module".to_owned()); - } - Sanitizer::Memory => { - modules_config.passes.push("msan".to_owned()) - } - Sanitizer::Thread => { - modules_config.passes.push("tsan".to_owned()) - } - _ => {} - } - } - if sess.opts.debugging_opts.profile { modules_config.passes.push("insert-gcov-profiling".to_owned()) } modules_config.pgo_gen = sess.opts.cg.profile_generate.clone(); modules_config.pgo_use = sess.opts.cg.profile_use.clone(); - + modules_config.sanitizer = sess.opts.debugging_opts.sanitizer.clone(); + modules_config.sanitizer_recover = sess.opts.debugging_opts.sanitizer_recover.clone(); + modules_config.sanitizer_memory_track_origins = + sess.opts.debugging_opts.sanitizer_memory_track_origins; modules_config.opt_level = Some(sess.opts.optimize); modules_config.opt_size = Some(sess.opts.optimize); @@ -1032,7 +1026,6 @@ fn start_executing_work( time_passes: sess.time_extended(), prof: sess.prof.clone(), exported_symbols, - plugin_passes: sess.plugin_llvm_passes.borrow().clone(), remark: sess.opts.cg.remark.clone(), worker: 0, incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()), @@ -1679,7 +1672,7 @@ impl Emitter for SharedEmitter { } drop(self.sender.send(SharedEmitterMessage::AbortIfErrors)); } - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&Lrc> { None } } @@ -1759,7 +1752,7 @@ impl OngoingCodegen { } }; - sess.cgu_reuse_tracker.check_expected_reuse(sess); + sess.cgu_reuse_tracker.check_expected_reuse(sess.diagnostic()); sess.abort_if_errors(); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index ee4ec7fb41..f6725e66f0 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -1,21 +1,32 @@ //! Codegen the completed AST to the LLVM IR. //! -//! Some functions here, such as codegen_block and codegen_expr, return a value -- -//! the result of the codegen to LLVM -- while others, such as codegen_fn -//! and mono_item, are called only for the side effect of adding a +//! Some functions here, such as `codegen_block` and `codegen_expr`, return a value -- +//! the result of the codegen to LLVM -- while others, such as `codegen_fn` +//! and `mono_item`, are called only for the side effect of adding a //! particular definition to the LLVM IR output we're producing. //! //! Hopefully useful general knowledge about codegen: //! -//! * There's no way to find out the `Ty` type of a Value. Doing so +//! * There's no way to find out the `Ty` type of a `Value`. Doing so //! would be "trying to get the eggs out of an omelette" (credit: //! pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`, //! but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int, //! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`. -use crate::{ModuleCodegen, ModuleKind, CachedModuleCodegen}; +use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}; +use crate::back::write::{ + OngoingCodegen, start_async_codegen, submit_pre_lto_module_to_llvm, + submit_post_lto_module_to_llvm, +}; +use crate::common::{RealPredicate, TypeKind, IntPredicate}; +use crate::meth; +use crate::mir; +use crate::mir::operand::OperandValue; +use crate::mir::place::PlaceRef; +use crate::traits::*; -use rustc::dep_graph::cgu_reuse_tracker::CguReuse; +use rustc::hir; +use rustc_session::cgu_reuse_tracker::CguReuse; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::lang_items::StartFnLangItem; @@ -23,6 +34,7 @@ use rustc::middle::weak_lang_items; use rustc::mir::mono::{CodegenUnitNameBuilder, CodegenUnit, MonoItem}; use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc::ty::query::Providers; use rustc::middle::cstore::{self, LinkagePreference}; use rustc::util::common::{time, print_time_passes_entry, set_time_depth, time_depth}; @@ -31,25 +43,12 @@ use rustc::session::Session; use rustc::util::nodemap::FxHashMap; use rustc_index::vec::Idx; use rustc_codegen_utils::{symbol_names_test, check_for_rustc_errors_attr}; -use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; -use crate::mir::place::PlaceRef; -use crate::back::write::{OngoingCodegen, start_async_codegen, submit_pre_lto_module_to_llvm, - submit_post_lto_module_to_llvm}; -use crate::{MemFlags, CrateInfo}; -use crate::common::{RealPredicate, TypeKind, IntPredicate}; -use crate::meth; -use crate::mir; - -use crate::traits::*; +use syntax::attr; +use syntax_pos::Span; use std::cmp; use std::ops::{Deref, DerefMut}; use std::time::{Instant, Duration}; -use syntax_pos::Span; -use syntax::attr; -use rustc::hir; - -use crate::mir::operand::OperandValue; pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind, signed: bool) @@ -116,9 +115,8 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// Retrieves the information we are losing (making dynamic) in an unsizing /// adjustment. /// -/// The `old_info` argument is a bit funny. It is intended for use -/// in an upcast, where the new vtable for an object will be derived -/// from the old one. +/// The `old_info` argument is a bit odd. It is intended for use in an upcast, +/// where the new vtable for an object will be derived from the old one. pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, source: Ty<'tcx>, @@ -140,16 +138,19 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>( (_, &ty::Dynamic(ref data, ..)) => { let vtable_ptr = cx.layout_of(cx.tcx().mk_mut_ptr(target)) .field(cx, FAT_PTR_EXTRA); - cx.const_ptrcast(meth::get_vtable(cx, source, data.principal()), - cx.backend_type(vtable_ptr)) + cx.const_ptrcast( + meth::get_vtable(cx, source, data.principal()), + cx.backend_type(vtable_ptr), + ) } - _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", - source, - target), + _ => bug!( + "unsized_info: invalid unsizing {:?} -> {:?}", + source, target + ), } } -/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer. +/// Coerces `src` to `dst_ty`. `src_ty` must be a thin pointer. pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, src: Bx::Value, @@ -199,8 +200,8 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -/// Coerce `src`, which is a reference to a value of type `src_ty`, -/// to a value of type `dst_ty` and store the result in `dst` +/// Coerces `src`, which is a reference to a value of type `src_ty`, +/// to a value of type `dst_ty`, and stores the result in `dst`. pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, src: PlaceRef<'tcx, Bx::Value>, @@ -244,15 +245,17 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if src_f.layout.ty == dst_f.layout.ty { memcpy_ty(bx, dst_f.llval, dst_f.align, src_f.llval, src_f.align, - src_f.layout, MemFlags::empty()); + src_f.layout, MemFlags::empty()); } else { coerce_unsized_into(bx, src_f, dst_f); } } } - _ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}", - src_ty, - dst_ty), + _ => bug!( + "coerce_unsized_into: invalid coercion {:?} -> {:?}", + src_ty, + dst_ty, + ), } } @@ -365,13 +368,7 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( // release builds. info!("codegen_instance({})", instance); - let sig = instance.fn_sig(cx.tcx()); - let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - - let lldecl = cx.get_fn(instance); - - let mir = cx.tcx().instance_mir(instance.def); - mir::codegen_mir::(cx, lldecl, &mir, instance, sig); + mir::codegen_mir::(cx, instance); } /// Creates the `main` function which will initialize the rust runtime and call @@ -549,11 +546,10 @@ pub fn codegen_crate( }); let allocator_module = if any_dynamic_crate { None - } else if let Some(kind) = *tcx.sess.allocator_kind.get() { + } else if let Some(kind) = tcx.allocator_kind() { let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], - Some("allocator")).as_str() - .to_string(); + Some("allocator")).to_string(); let mut modules = backend.new_metadata(tcx, &llmod_id); time(tcx.sess, "write allocator module", || { backend.codegen_allocator(tcx, &mut modules, kind) @@ -576,8 +572,7 @@ pub fn codegen_crate( // Codegen the encoded metadata. let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], - Some("metadata")).as_str() - .to_string(); + Some("metadata")).to_string(); let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name); time(tcx.sess, "write compressed metadata", || { backend.write_compressed_metadata(tcx, &ongoing_codegen.metadata, diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs index ac39ca9847..9bebca9396 100644 --- a/src/librustc_codegen_ssa/common.rs +++ b/src/librustc_codegen_ssa/common.rs @@ -12,6 +12,8 @@ use crate::traits::*; use rustc::hir; use crate::traits::BuilderMethods; +use rustc_error_codes::*; + pub enum IntPredicate { IntEQ, IntNE, diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index 166a74fe48..8ff08e832d 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -37,9 +37,9 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), ty::Never => output.push_str("!"), - ty::Int(int_ty) => output.push_str(int_ty.ty_to_string()), - ty::Uint(uint_ty) => output.push_str(uint_ty.ty_to_string()), - ty::Float(float_ty) => output.push_str(float_ty.ty_to_string()), + ty::Int(int_ty) => output.push_str(int_ty.name_str()), + ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()), + ty::Float(float_ty) => output.push_str(float_ty.name_str()), ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output), ty::Adt(def, substs) => { push_item_name(tcx, def.did, qualified, output); @@ -62,8 +62,8 @@ pub fn push_debuginfo_type_name<'tcx>( output.push('*'); } match mutbl { - hir::MutImmutable => output.push_str("const "), - hir::MutMutable => output.push_str("mut "), + hir::Mutability::Immutable => output.push_str("const "), + hir::Mutability::Mutable => output.push_str("mut "), } push_debuginfo_type_name(tcx, inner_type, true, output, visited); @@ -76,9 +76,7 @@ pub fn push_debuginfo_type_name<'tcx>( if !cpp_like_names { output.push('&'); } - if mutbl == hir::MutMutable { - output.push_str("mut "); - } + output.push_str(mutbl.prefix_str()); push_debuginfo_type_name(tcx, inner_type, true, output, visited); @@ -140,9 +138,7 @@ pub fn push_debuginfo_type_name<'tcx>( let sig = t.fn_sig(tcx); - if sig.unsafety() == hir::Unsafety::Unsafe { - output.push_str("unsafe "); - } + output.push_str(sig.unsafety().prefix_str()); let abi = sig.abi(); if abi != rustc_target::spec::abi::Abi::Rust { diff --git a/src/librustc_codegen_ssa/error_codes.rs b/src/librustc_codegen_ssa/error_codes.rs deleted file mode 100644 index 02e26d8f6e..0000000000 --- a/src/librustc_codegen_ssa/error_codes.rs +++ /dev/null @@ -1,71 +0,0 @@ -syntax::register_diagnostics! { - -E0511: r##" -Invalid monomorphization of an intrinsic function was used. Erroneous code -example: - -```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) -#![feature(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} - -fn main() { - unsafe { simd_add(0, 1); } - // error: invalid monomorphization of `simd_add` intrinsic -} -``` - -The generic type has to be a SIMD type. Example: - -``` -#![feature(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -#[derive(Copy, Clone)] -struct i32x2(i32, i32); - -extern "platform-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} - -unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! -``` -"##, - -E0668: r##" -Malformed inline assembly rejected by LLVM. - -LLVM checks the validity of the constraints and the assembly string passed to -it. This error implies that LLVM seems something wrong with the inline -assembly call. - -In particular, it can happen if you forgot the closing bracket of a register -constraint (see issue #51430): -```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) -#![feature(asm)] - -fn main() { - let rax: u64; - unsafe { - asm!("" :"={rax"(rax)); - println!("Accumulator is: {}", rax); - } -} -``` -"##, - -E0669: r##" -Cannot convert inline assembly operand to a single LLVM value. - -This error usually happens when trying to pass in a value to an input inline -assembly operand that is actually a pair of values. In particular, this can -happen when trying to pass in a slice, for instance a `&str`. In Rust, these -values are represented internally as a pair of values, the pointer and its -length. When passed as an input operand, this pair of values can not be -coerced into a register and thus we must fail with an error. -"##, - -} diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index dd75883f97..9919666027 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -1,5 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(core_intrinsics)] @@ -35,8 +36,6 @@ use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary}; use rustc::middle::dependency_format::Dependencies; use syntax_pos::symbol::Symbol; -mod error_codes; - pub mod common; pub mod traits; pub mod mir; @@ -59,7 +58,8 @@ pub struct ModuleCodegen { pub kind: ModuleKind, } -pub const METADATA_FILENAME: &str = "rust.metadata.bin"; +// FIXME(eddyb) maybe include the crate name in this? +pub const METADATA_FILENAME: &str = "lib.rmeta"; pub const RLIB_BYTECODE_EXTENSION: &str = "bc.z"; @@ -69,22 +69,14 @@ impl ModuleCodegen { emit_bc: bool, emit_bc_compressed: bool, outputs: &OutputFilenames) -> CompiledModule { - let object = if emit_obj { - Some(outputs.temp_path(OutputType::Object, Some(&self.name))) - } else { - None - }; - let bytecode = if emit_bc { - Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))) - } else { - None - }; - let bytecode_compressed = if emit_bc_compressed { - Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)) - .with_extension(RLIB_BYTECODE_EXTENSION)) - } else { - None - }; + let object = emit_obj + .then(|| outputs.temp_path(OutputType::Object, Some(&self.name))); + let bytecode = emit_bc + .then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name))); + let bytecode_compressed = emit_bc_compressed.then(|| { + outputs.temp_path(OutputType::Bitcode, Some(&self.name)) + .with_extension(RLIB_BYTECODE_EXTENSION) + }); CompiledModule { name: self.name.clone(), diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 266d2e5b18..c14618a15e 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -1,8 +1,7 @@ -use rustc_target::abi::call::FnType; - use crate::traits::*; use rustc::ty::{self, Ty, Instance}; +use rustc_target::abi::call::FnAbi; #[derive(Copy, Clone, Debug)] pub struct VirtualIndex(u64); @@ -20,20 +19,20 @@ impl<'a, 'tcx> VirtualIndex { self, bx: &mut Bx, llvtable: Bx::Value, - fn_ty: &FnType<'tcx, Ty<'tcx>> + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> Bx::Value { // Load the data pointer from the object. debug!("get_fn({:?}, {:?})", llvtable, self); let llvtable = bx.pointercast( llvtable, - bx.type_ptr_to(bx.fn_ptr_backend_type(fn_ty)) + bx.type_ptr_to(bx.fn_ptr_backend_type(fn_abi)) ); let ptr_align = bx.tcx().data_layout.pointer_align.abi; let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]); let ptr = bx.load(gep, ptr_align); bx.nonnull_metadata(ptr); - // Vtable loads are invariant + // Vtable loads are invariant. bx.set_invariant_load(ptr); ptr } @@ -41,7 +40,7 @@ impl<'a, 'tcx> VirtualIndex { pub fn get_usize>( self, bx: &mut Bx, - llvtable: Bx::Value + llvtable: Bx::Value, ) -> Bx::Value { // Load the data pointer from the object. debug!("get_int({:?}, {:?})", llvtable, self); @@ -50,7 +49,7 @@ impl<'a, 'tcx> VirtualIndex { let usize_align = bx.tcx().data_layout.pointer_align.abi; let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]); let ptr = bx.load(gep, usize_align); - // Vtable loads are invariant + // Vtable loads are invariant. bx.set_invariant_load(ptr); ptr } @@ -63,7 +62,7 @@ impl<'a, 'tcx> VirtualIndex { /// /// The `trait_ref` encodes the erased self type. Hence if we are /// making an object `Foo` from a value of type `Foo`, then -/// `trait_ref` would map `T:Trait`. +/// `trait_ref` would map `T: Trait`. pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, ty: Ty<'tcx>, @@ -78,7 +77,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( return val; } - // Not in the cache. Build it. + // Not in the cache; build it. let nullptr = cx.const_null(cx.type_i8p()); let methods_root; @@ -105,7 +104,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let layout = cx.layout_of(ty); // ///////////////////////////////////////////////////////////////////////////////////////////// // If you touch this code, be sure to also make the corresponding changes to - // `get_vtable` in rust_mir/interpret/traits.rs + // `get_vtable` in `rust_mir/interpret/traits.rs`. // ///////////////////////////////////////////////////////////////////////////////////////////// let components: Vec<_> = [ cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)), diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 2e5dc3db31..6c627085b2 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -5,7 +5,9 @@ use rustc_index::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::vec::{Idx, IndexVec}; use rustc::mir::{self, Location, TerminatorKind}; -use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; +use rustc::mir::visit::{ + Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext, NonUseContext, +}; use rustc::mir::traversal; use rustc::session::config::DebugInfo; use rustc::ty; @@ -27,7 +29,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead // of putting everything in allocas just so we can use llvm.dbg.declare. if fx.cx.sess().opts.debuginfo == DebugInfo::Full { - if mir.local_kind(local) == mir::LocalKind::Arg || decl.name.is_some() { + if fx.mir.local_kind(local) == mir::LocalKind::Arg { analyzer.not_ssa(local); continue; } @@ -68,9 +70,10 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self { let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); + let dominators = fx.mir.dominators(); let mut analyzer = LocalAnalyzer { fx, - dominators: fx.mir.dominators(), + dominators, non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()), first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls) }; @@ -114,6 +117,12 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { let cx = self.fx.cx; if let [proj_base @ .., elem] = place_ref.projection { + let mut base_context = if context.is_mutating_use() { + PlaceContext::MutatingUse(MutatingUseContext::Projection) + } else { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) + }; + // Allow uses of projections that are ZSTs or from scalar fields. let is_consume = match context { PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | @@ -122,7 +131,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; if is_consume { let base_ty = - mir::Place::ty_from(place_ref.base, proj_base, self.fx.mir, cx.tcx()); + mir::Place::ty_from(place_ref.base, proj_base, *self.fx.mir, cx.tcx()); let base_ty = self.fx.monomorphize(&base_ty); // ZSTs don't require any actual memory access. @@ -145,47 +154,81 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { // Recurse with the same context, instead of `Projection`, // potentially stopping at non-operand projections, // which would trigger `not_ssa` on locals. - self.process_place( - &mir::PlaceRef { - base: place_ref.base, - projection: proj_base, - }, - context, - location, - ); - return; + base_context = context; } } } - // A deref projection only reads the pointer, never needs the place. if let mir::ProjectionElem::Deref = elem { - self.process_place( - &mir::PlaceRef { - base: place_ref.base, - projection: proj_base, - }, + // Deref projections typically only read the pointer. + // (the exception being `VarDebugInfo` contexts, handled below) + base_context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy); + + // Indirect debuginfo requires going through memory, that only + // the debugger accesses, following our emitted DWARF pointer ops. + // + // FIXME(eddyb) Investigate the possibility of relaxing this, but + // note that `llvm.dbg.declare` *must* be used for indirect places, + // even if we start using `llvm.dbg.value` for all other cases, + // as we don't necessarily know when the value changes, but only + // where it lives in memory. + // + // It's possible `llvm.dbg.declare` could support starting from + // a pointer that doesn't point to an `alloca`, but this would + // only be useful if we know the pointer being `Deref`'d comes + // from an immutable place, and if `llvm.dbg.declare` calls + // must be at the very start of the function, then only function + // arguments could contain such pointers. + if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) { + // We use `NonUseContext::VarDebugInfo` for the base, + // which might not force the base local to memory, + // so we have to do it manually. + if let mir::PlaceBase::Local(local) = place_ref.base { + self.visit_local(&local, context, location); + } + } + } + + // `NonUseContext::VarDebugInfo` needs to flow all the + // way down to the base local (see `visit_local`). + if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) { + base_context = context; + } + + self.process_place( + &mir::PlaceRef { + base: place_ref.base, + projection: proj_base, + }, + base_context, + location + ); + // HACK(eddyb) this emulates the old `visit_projection_elem`, this + // entire `visit_place`-like `process_place` method should be rewritten, + // now that we have moved to the "slice of projections" representation. + if let mir::ProjectionElem::Index(local) = elem { + self.visit_local( + local, PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), location ); - return; } - } + } else { + // FIXME this is super_place code, is repeated here to avoid cloning place or changing + // visit_place API + let mut context = context; - // FIXME this is super_place code, is repeated here to avoid cloning place or changing - // visit_place API - let mut context = context; + if !place_ref.projection.is_empty() { + context = if context.is_mutating_use() { + PlaceContext::MutatingUse(MutatingUseContext::Projection) + } else { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) + }; + } - if !place_ref.projection.is_empty() { - context = if context.is_mutating_use() { - PlaceContext::MutatingUse(MutatingUseContext::Projection) - } else { - PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) - }; + self.visit_place_base(place_ref.base, context, location); + self.visit_projection(place_ref.base, place_ref.projection, context, location); } - - self.visit_place_base(place_ref.base, context, location); - self.visit_projection(place_ref.base, place_ref.projection, context, location); } } @@ -264,6 +307,15 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> self.assign(local, location); } + PlaceContext::NonUse(NonUseContext::VarDebugInfo) => { + // We need to keep locals in `alloca`s for debuginfo. + // FIXME(eddyb): We should figure out how to use `llvm.dbg.value` instead + // of putting everything in allocas just so we can use `llvm.dbg.declare`. + if self.fx.cx.sess().opts.debuginfo == DebugInfo::Full { + self.not_ssa(local); + } + } + PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {} diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 79855311f3..dabd097b00 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -1,10 +1,10 @@ use rustc_index::vec::Idx; use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable, Instance}; -use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt}; +use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnAbiExt}; use rustc::mir::{self, PlaceBase, Static, StaticKind}; use rustc::mir::interpret::PanicInfo; -use rustc_target::abi::call::{ArgType, FnType, PassMode}; +use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::abi::Abi; use crate::base; use crate::MemFlags; @@ -24,28 +24,28 @@ use super::operand::OperandValue::{Pair, Ref, Immediate}; /// Used by `FunctionCx::codegen_terminator` for emitting common patterns /// e.g., creating a basic block, calling a function, etc. -struct TerminatorCodegenHelper<'a, 'tcx> { - bb: &'a mir::BasicBlock, - terminator: &'a mir::Terminator<'tcx>, +struct TerminatorCodegenHelper<'tcx> { + bb: mir::BasicBlock, + terminator: &'tcx mir::Terminator<'tcx>, funclet_bb: Option, } -impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { +impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { /// Returns the associated funclet from `FunctionCx::funclets` for the /// `funclet_bb` member if it is not `None`. - fn funclet<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, - ) -> Option<&'c Bx::Funclet> { + fx: &'b mut FunctionCx<'a, 'tcx, Bx>, + ) -> Option<&'b Bx::Funclet> { match self.funclet_bb { Some(funcl) => fx.funclets[funcl].as_ref(), None => None, } } - fn lltarget<'b, 'c, Bx: BuilderMethods<'b, 'tcx>>( + fn lltarget>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; @@ -63,9 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } /// Create a basic block. - fn llblock<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn llblock>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, target: mir::BasicBlock, ) -> Bx::BasicBlock { let (lltarget, is_cleanupret) = self.lltarget(fx, target); @@ -83,9 +83,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } } - fn funclet_br<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn funclet_br>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, target: mir::BasicBlock, ) { @@ -99,13 +99,13 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } } - /// Call `fn_ptr` of `fn_ty` with the arguments `llargs`, the optional + /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional /// return destination `destination` and the cleanup function `cleanup`. - fn do_call<'c, 'b, Bx: BuilderMethods<'b, 'tcx>>( + fn do_call>( &self, - fx: &'c mut FunctionCx<'b, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, - fn_ty: FnType<'tcx, Ty<'tcx>>, + fn_abi: FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, @@ -122,17 +122,17 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { ret_bx, self.llblock(fx, cleanup), self.funclet(fx)); - bx.apply_attrs_callsite(&fn_ty, invokeret); + bx.apply_attrs_callsite(&fn_abi, invokeret); if let Some((ret_dest, target)) = destination { let mut ret_bx = fx.build_block(target); fx.set_debug_loc(&mut ret_bx, self.terminator.source_info); - fx.store_return(&mut ret_bx, ret_dest, &fn_ty.ret, invokeret); + fx.store_return(&mut ret_bx, ret_dest, &fn_abi.ret, invokeret); } } else { let llret = bx.call(fn_ptr, &llargs, self.funclet(fx)); - bx.apply_attrs_callsite(&fn_ty, llret); - if fx.mir[*self.bb].is_cleanup { + bx.apply_attrs_callsite(&fn_abi, llret); + if fx.mir[self.bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested // struct, there are "symmetry" issues that cause @@ -141,7 +141,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } if let Some((ret_dest, target)) = destination { - fx.store_return(bx, ret_dest, &fn_ty.ret, llret); + fx.store_return(bx, ret_dest, &fn_abi.ret, llret); self.funclet_br(fx, bx, target); } else { bx.unreachable(); @@ -151,15 +151,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { // Generate sideeffect intrinsic if jumping to any of the targets can form // a loop. - fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( + fn maybe_sideeffect>( &self, - mir: &'b mir::Body<'tcx>, + mir: mir::ReadOnlyBodyAndCache<'tcx, 'tcx>, bx: &mut Bx, targets: &[mir::BasicBlock], ) { if bx.tcx().sess.opts.debugging_opts.insert_sideeffect { - if targets.iter().any(|target| { - *target <= *self.bb + if targets.iter().any(|&target| { + target <= self.bb && target .start_location() .is_predecessor_of(self.bb.start_location(), mir) @@ -173,9 +173,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { /// Codegen implementations for some terminator variants. impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { /// Generates code for a `Resume` terminator. - fn codegen_resume_terminator<'b>( + fn codegen_resume_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, ) { if let Some(funclet) = helper.funclet(self) { @@ -201,9 +201,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - fn codegen_switchint_terminator<'b>( + fn codegen_switchint_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, discr: &mir::Operand<'tcx>, switch_ty: Ty<'tcx>, @@ -248,9 +248,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn codegen_return_terminator(&mut self, mut bx: Bx) { // Call `va_end` if this is the definition of a C-variadic function. - if self.fn_ty.c_variadic { + if self.fn_abi.c_variadic { // The `VaList` "spoofed" argument is just after all the real arguments. - let va_list_arg_idx = self.fn_ty.args.len(); + let va_list_arg_idx = self.fn_abi.args.len(); match self.locals[mir::Local::new(1 + va_list_arg_idx)] { LocalRef::Place(va_list) => { bx.va_end(va_list.llval); @@ -258,14 +258,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("C-variadic function must have a `VaList` place"), } } - if self.fn_ty.ret.layout.abi.is_uninhabited() { + if self.fn_abi.ret.layout.abi.is_uninhabited() { // Functions with uninhabited return values are marked `noreturn`, // so we should make sure that we never actually do. + // We play it safe by using a well-defined `abort`, but we could go for immediate UB + // if that turns out to be helpful. bx.abort(); + // `abort` does not terminate the block, so we still need to generate + // an `unreachable` terminator after it. bx.unreachable(); return; } - let llval = match self.fn_ty.ret.mode { + let llval = match self.fn_abi.ret.mode { PassMode::Ignore | PassMode::Indirect(..) => { bx.ret_void(); return; @@ -296,7 +300,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llslot = match op.val { Immediate(_) | Pair(..) => { let scratch = - PlaceRef::alloca(&mut bx, self.fn_ty.ret.layout); + PlaceRef::alloca(&mut bx, self.fn_abi.ret.layout); op.val.store(&mut bx, scratch); scratch.llval } @@ -309,22 +313,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let addr = bx.pointercast(llslot, bx.type_ptr_to( bx.cast_backend_type(&cast_ty) )); - bx.load(addr, self.fn_ty.ret.layout.align.abi) + bx.load(addr, self.fn_abi.ret.layout.align.abi) } }; bx.ret(llval); } - fn codegen_drop_terminator<'b>( + fn codegen_drop_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, location: &mir::Place<'tcx>, target: mir::BasicBlock, unwind: Option, ) { - let ty = location.ty(self.mir, bx.tcx()).ty; + let ty = location.ty(*self.mir, bx.tcx()).ty; let ty = self.monomorphize(&ty); let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); @@ -344,32 +348,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args1 = [place.llval]; &args1[..] }; - let (drop_fn, fn_ty) = match ty.kind { + let (drop_fn, fn_abi) = match ty.kind { + // FIXME(eddyb) perhaps move some of this logic into + // `Instance::resolve_drop_in_place`? ty::Dynamic(..) => { - let sig = drop_fn.fn_sig(self.cx.tcx()); - let sig = self.cx.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - let fn_ty = FnType::new_vtable(&bx, sig, &[]); + let virtual_drop = Instance { + def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), + substs: drop_fn.substs, + }; + let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]); let vtable = args[1]; args = &args[..1]; - (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty) + (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_abi), fn_abi) } _ => { (bx.get_fn_addr(drop_fn), - FnType::of_instance(&bx, drop_fn)) + FnAbi::of_instance(&bx, drop_fn, &[])) } }; helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.do_call(self, &mut bx, fn_ty, drop_fn, args, + helper.do_call(self, &mut bx, fn_abi, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); } - fn codegen_assert_terminator<'b>( + fn codegen_assert_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, cond: &mir::Operand<'tcx>, @@ -439,16 +444,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Obtain the panic entry point. let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_ty = FnType::of_instance(&bx, instance); + let fn_abi = FnAbi::of_instance(&bx, instance, &[]); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. - helper.do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup); + helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); } - fn codegen_call_terminator<'b>( + fn codegen_call_terminator( &mut self, - helper: TerminatorCodegenHelper<'b, 'tcx>, + helper: TerminatorCodegenHelper<'tcx>, mut bx: Bx, terminator: &mir::Terminator<'tcx>, func: &mir::Operand<'tcx>, @@ -474,12 +479,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("{} is not callable", callee.layout.ty), }; let def = instance.map(|i| i.def); + + if let Some(ty::InstanceDef::DropGlue(_, None)) = def { + // Empty drop glue; a no-op. + let &(_, target) = destination.as_ref().unwrap(); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + return; + } + + // FIXME(eddyb) avoid computing this if possible, when `instance` is + // available - right now `sig` is only needed for getting the `abi` + // and figuring out how many extra args were passed to a C-variadic `fn`. let sig = callee.layout.ty.fn_sig(bx.tcx()); - let sig = bx.tcx().normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &sig, - ); - let abi = sig.abi; + let abi = sig.abi(); // Handle intrinsics old codegen wants Expr's for, ourselves. let intrinsic = match def { @@ -489,6 +502,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let intrinsic = intrinsic.as_ref().map(|s| &s[..]); + let extra_args = &args[sig.inputs().skip_binder().len()..]; + let extra_args = extra_args.iter().map(|op_arg| { + let op_ty = op_arg.ty(*self.mir, bx.tcx()); + self.monomorphize(&op_ty) + }).collect::>(); + + let fn_abi = match instance { + Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), + None => FnAbi::of_fn_ptr(&bx, sig, &extra_args) + }; + if intrinsic == Some("transmute") { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; @@ -502,31 +526,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // we can do what we like. Here, we declare that transmuting // into an uninhabited type is impossible, so anything following // it must be unreachable. - assert_eq!(bx.layout_of(sig.output()).abi, layout::Abi::Uninhabited); + assert_eq!(fn_abi.ret.layout.abi, layout::Abi::Uninhabited); bx.unreachable(); } return; } - let extra_args = &args[sig.inputs().len()..]; - let extra_args = extra_args.iter().map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); - self.monomorphize(&op_ty) - }).collect::>(); - - let fn_ty = match def { - Some(ty::InstanceDef::Virtual(..)) => { - FnType::new_vtable(&bx, sig, &extra_args) - } - Some(ty::InstanceDef::DropGlue(_, None)) => { - // Empty drop glue; a no-op. - let &(_, target) = destination.as_ref().unwrap(); - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); - return; - } - _ => FnType::new(&bx, sig, &extra_args) - }; + // For normal codegen, this Miri-specific intrinsic is just a NOP. + if intrinsic == Some("miri_start_panic") { + let target = destination.as_ref().unwrap().1; + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); + return; + } // Emit a panic or a no-op for `panic_if_uninhabited`. if intrinsic == Some("panic_if_uninhabited") { @@ -541,7 +553,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_ty = FnType::of_instance(&bx, instance); + let fn_abi = FnAbi::of_instance(&bx, instance, &[]); let llfn = bx.get_fn_addr(instance); if let Some((_, target)) = destination.as_ref() { @@ -551,7 +563,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper.do_call( self, &mut bx, - fn_ty, + fn_abi, llfn, &[msg.0, msg.1, location], destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), @@ -561,19 +573,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // a NOP let target = destination.as_ref().unwrap().1; helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target); + helper.funclet_br(self, &mut bx, target) } return; } // The arguments we'll be passing. Plus one to account for outptr, if used. - let arg_count = fn_ty.args.len() + fn_ty.ret.is_indirect() as usize; + let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; let mut llargs = Vec::with_capacity(arg_count); // Prepare the return value destination let ret_dest = if let Some((ref dest, _)) = *destination { let is_intrinsic = intrinsic.is_some(); - self.make_return_dest(&mut bx, dest, &fn_ty.ret, &mut llargs, + self.make_return_dest(&mut bx, dest, &fn_abi.ret, &mut llargs, is_intrinsic) } else { ReturnDest::Nothing @@ -586,7 +598,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { location.val.store(&mut bx, tmp); } - self.store_return(&mut bx, ret_dest, &fn_ty.ret, location.immediate()); + self.store_return(&mut bx, ret_dest, &fn_abi.ret, location.immediate()); helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); helper.funclet_br(self, &mut bx, *target); @@ -596,9 +608,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if intrinsic.is_some() && intrinsic != Some("drop_in_place") { let dest = match ret_dest { - _ if fn_ty.ret.is_indirect() => llargs[0], + _ if fn_abi.ret.is_indirect() => llargs[0], ReturnDest::Nothing => - bx.const_undef(bx.type_ptr_to(bx.memory_ty(&fn_ty.ret))), + bx.const_undef(bx.type_ptr_to(bx.arg_memory_ty(&fn_abi.ret))), ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.llval, ReturnDest::DirectOperand(_) => @@ -667,11 +679,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }).collect(); - bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest, + bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_abi, &args, dest, terminator.source_info.span); if let ReturnDest::IndirectOperand(dst, _) = ret_dest { - self.store_return(&mut bx, ret_dest, &fn_ty.ret, dst.llval); + self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval); } if let Some((_, target)) = *destination { @@ -706,7 +718,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 'descend_newtypes: while !op.layout.ty.is_unsafe_ptr() && !op.layout.ty.is_region_ptr() { - 'iter_fields: for i in 0..op.layout.fields.count() { + for i in 0..op.layout.fields.count() { let field = op.extract_field(&mut bx, i); if !field.layout.is_zst() { // we found the one non-zero-sized field that is allowed @@ -726,7 +738,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match op.val { Pair(data_ptr, meta) => { llfn = Some(meth::VirtualIndex::from_index(idx) - .get_fn(&mut bx, meta, &fn_ty)); + .get_fn(&mut bx, meta, &fn_abi)); llargs.push(data_ptr); continue 'make_args } @@ -735,7 +747,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else if let Ref(data_ptr, Some(meta), _) = op.val { // by-value dynamic dispatch llfn = Some(meth::VirtualIndex::from_index(idx) - .get_fn(&mut bx, meta, &fn_ty)); + .get_fn(&mut bx, meta, &fn_abi)); llargs.push(data_ptr); continue; } else { @@ -755,11 +767,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => {} } - self.codegen_argument(&mut bx, op, &mut llargs, &fn_ty.args[i]); + self.codegen_argument(&mut bx, op, &mut llargs, &fn_abi.args[i]); } if let Some(tup) = untuple { self.codegen_arguments_untupled(&mut bx, tup, &mut llargs, - &fn_ty.args[first_args.len()..]) + &fn_abi.args[first_args.len()..]) + } + + let needs_location = + instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx())); + if needs_location { + assert_eq!( + fn_abi.args.len(), args.len() + 1, + "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", + ); + let location = self.get_caller_location(&mut bx, span); + let last_arg = fn_abi.args.last().unwrap(); + self.codegen_argument(&mut bx, location, &mut llargs, last_arg); } let fn_ptr = match (llfn, instance) { @@ -771,7 +795,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some((_, target)) = destination.as_ref() { helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); } - helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, + helper.do_call(self, &mut bx, fn_abi, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), cleanup); } @@ -783,7 +807,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bb: mir::BasicBlock, ) { let mut bx = self.build_block(bb); - let data = &self.mir[bb]; + let mir = self.mir; + let data = &mir[bb]; debug!("codegen_block({:?}={:?})", bb, data); @@ -798,14 +823,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, mut bx: Bx, bb: mir::BasicBlock, - terminator: &mir::Terminator<'tcx> + terminator: &'tcx mir::Terminator<'tcx> ) { debug!("codegen_terminator: {:?}", terminator); // Create the cleanup bundle, if needed. let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb); let helper = TerminatorCodegenHelper { - bb: &bb, terminator, funclet_bb + bb, terminator, funclet_bb }; self.set_debug_loc(&mut bx, terminator.source_info); @@ -816,6 +841,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::TerminatorKind::Abort => { bx.abort(); + // `abort` does not terminate the block, so we still need to generate + // an `unreachable` terminator after it. bx.unreachable(); } @@ -874,7 +901,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, op: OperandRef<'tcx, Bx::Value>, llargs: &mut Vec, - arg: &ArgType<'tcx, Ty<'tcx>> + arg: &ArgAbi<'tcx, Ty<'tcx>> ) { // Fill padding with undef value, where applicable. if let Some(ty) = arg.pad { @@ -967,7 +994,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, operand: &mir::Operand<'tcx>, llargs: &mut Vec, - args: &[ArgType<'tcx, Ty<'tcx>>] + args: &[ArgAbi<'tcx, Ty<'tcx>>] ) { let tuple = self.codegen_operand(bx, operand); @@ -995,13 +1022,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, span: Span, ) -> OperandRef<'tcx, Bx::Value> { - let caller = bx.tcx().sess.source_map().lookup_char_pos(span.lo()); - let const_loc = bx.tcx().const_caller_location(( - Symbol::intern(&caller.file.name.to_string()), - caller.line as u32, - caller.col_display as u32 + 1, - )); - OperandRef::from_const(bx, const_loc) + self.caller_location.unwrap_or_else(|| { + let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); + let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo()); + let const_loc = bx.tcx().const_caller_location(( + Symbol::intern(&caller.file.name.to_string()), + caller.line as u32, + caller.col_display as u32 + 1, + )); + OperandRef::from_const(bx, const_loc) + }) } fn get_personality_slot( @@ -1041,7 +1071,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn landing_pad_uncached( &mut self, - target_bb: Bx::BasicBlock + target_bb: Bx::BasicBlock, ) -> Bx::BasicBlock { if base::wants_msvc_seh(self.cx.sess()) { span_bug!(self.mir.span, "landing pad was not inserted?") @@ -1095,7 +1125,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, bx: &mut Bx, dest: &mir::Place<'tcx>, - fn_ret: &ArgType<'tcx, Ty<'tcx>>, + fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec, is_intrinsic: bool ) -> ReturnDest<'tcx, Bx::Value> { // If the return is ignored, we can just return a do-nothing `ReturnDest`. @@ -1204,14 +1234,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, bx: &mut Bx, dest: ReturnDest<'tcx, Bx::Value>, - ret_ty: &ArgType<'tcx, Ty<'tcx>>, + ret_abi: &ArgAbi<'tcx, Ty<'tcx>>, llval: Bx::Value ) { use self::ReturnDest::*; match dest { Nothing => (), - Store(dst) => bx.store_arg_ty(&ret_ty, llval, dst), + Store(dst) => bx.store_arg(&ret_abi, llval, dst), IndirectOperand(tmp, index) => { let op = bx.load_operand(tmp); tmp.storage_dead(bx); @@ -1219,15 +1249,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } DirectOperand(index) => { // If there is a cast, we have to store and reload. - let op = if let PassMode::Cast(_) = ret_ty.mode { - let tmp = PlaceRef::alloca(bx, ret_ty.layout); + let op = if let PassMode::Cast(_) = ret_abi.mode { + let tmp = PlaceRef::alloca(bx, ret_abi.layout); tmp.storage_live(bx); - bx.store_arg_ty(&ret_ty, llval, tmp); + bx.store_arg(&ret_abi, llval, tmp); let op = bx.load_operand(tmp); tmp.storage_dead(bx); op } else { - OperandRef::from_immediate_or_packed_pair(bx, llval, ret_ty.layout) + OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout) }; self.locals[index] = LocalRef::Operand(Some(op)); } diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 72d098eb31..fb8f504d04 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -5,17 +5,44 @@ use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, HasTyCtxt}; use syntax::source_map::Span; use crate::traits::*; +use crate::mir::operand::OperandRef; use super::FunctionCx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + pub fn eval_mir_constant_to_operand( + &mut self, + bx: &mut Bx, + constant: &mir::Constant<'tcx>, + ) -> Result, ErrorHandled> { + match constant.literal.val { + // Special case unevaluated statics, because statics have an identity and thus should + // use `get_static` to get at their id. + // FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics + // always produce `&STATIC`. This may also simplify how const eval works with statics. + ty::ConstKind::Unevaluated(def_id, substs) + if self.cx.tcx().is_static(def_id) => { + assert!(substs.is_empty(), "we don't support generic statics yet"); + let static_ = bx.get_static(def_id); + // we treat operands referring to statics as if they were `&STATIC` instead + let ptr_ty = self.cx.tcx().mk_mut_ptr(self.monomorphize(&constant.literal.ty)); + let layout = bx.layout_of(ptr_ty); + Ok(OperandRef::from_immediate_or_packed_pair(bx, static_, layout)) + } + _ => { + let val = self.eval_mir_constant(constant)?; + Ok(OperandRef::from_const(bx, val)) + } + } + } + pub fn eval_mir_constant( &mut self, constant: &mir::Constant<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { match constant.literal.val { - mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => { - let substs = self.monomorphize(substs); + ty::ConstKind::Unevaluated(def_id, substs) => { + let substs = self.monomorphize(&substs); let instance = ty::Instance::resolve( self.cx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs, ).unwrap(); diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs index c215db34cc..bb2679e214 100644 --- a/src/librustc_codegen_ssa/mir/debuginfo.rs +++ b/src/librustc_codegen_ssa/mir/debuginfo.rs @@ -1,12 +1,12 @@ -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::vec::IndexVec; use rustc::hir::def_id::CrateNum; use rustc::mir; use rustc::session::config::DebugInfo; -use rustc::ty::{self, TyCtxt}; -use rustc::ty::layout::{LayoutOf, Size, VariantIdx}; +use rustc::ty::TyCtxt; +use rustc::ty::layout::{LayoutOf, Size}; use crate::traits::*; -use syntax_pos::{BytePos, Span, Symbol}; +use syntax_pos::{BytePos, Span}; use syntax::symbol::kw; use super::{FunctionCx, LocalRef}; @@ -113,7 +113,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some(per_local) => &per_local[local], None => return, }; - let whole_local_var = vars.iter().find(|var| { + let whole_local_var = vars.iter().copied().find(|var| { var.place.projection.is_empty() }); let has_proj = || vars.iter().any(|var| { @@ -131,7 +131,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // be offset to account for the hidden environment? None } else { - Some(VarDebugInfo { + Some(mir::VarDebugInfo { name: kw::Invalid, source_info: self.mir.local_decls[local].source_info, place: local.into(), @@ -185,7 +185,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => return, }; - let vars = vars.iter().chain(if whole_local_var.is_none() { + let vars = vars.iter().copied().chain(if whole_local_var.is_none() { fallback_var.as_ref() } else { None @@ -253,133 +253,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } +/// Partition all `VarDebuginfo` in `body`, by their base `Local`. pub fn per_local_var_debug_info( tcx: TyCtxt<'tcx>, - body: &mir::Body<'tcx>, -) -> Option>>> { + body: &'a mir::Body<'tcx>, +) -> Option>>> { if tcx.sess.opts.debuginfo == DebugInfo::Full || !tcx.sess.fewer_names() { let mut per_local = IndexVec::from_elem(vec![], &body.local_decls); - for (local, decl) in body.local_decls.iter_enumerated() { - if let Some(name) = decl.name { - per_local[local].push(VarDebugInfo { - name, - source_info: mir::SourceInfo { - span: decl.source_info.span, - scope: decl.visibility_scope, - }, - place: local.into(), - }); - } - } - - let upvar_debuginfo = &body.__upvar_debuginfo_codegen_only_do_not_use; - if !upvar_debuginfo.is_empty() { - - let env_arg = mir::Local::new(1); - let mut env_projs = vec![]; - - let pin_did = tcx.lang_items().pin_type(); - match body.local_decls[env_arg].ty.kind { - ty::RawPtr(_) | - ty::Ref(..) => { - env_projs.push(mir::ProjectionElem::Deref); - } - ty::Adt(def, substs) if Some(def.did) == pin_did => { - if let ty::Ref(..) = substs.type_at(0).kind { - env_projs.push(mir::ProjectionElem::Field( - mir::Field::new(0), - // HACK(eddyb) field types aren't used or needed here. - tcx.types.err, - )); - env_projs.push(mir::ProjectionElem::Deref); - } - } - _ => {} - } - - let extra_locals = { - let upvars = upvar_debuginfo - .iter() - .enumerate() - .map(|(i, upvar)| { - let source_info = mir::SourceInfo { - span: body.span, - scope: mir::OUTERMOST_SOURCE_SCOPE, - }; - (None, i, upvar.debug_name, upvar.by_ref, source_info) - }); - - let generator_fields = body.generator_layout.as_ref().map(|generator_layout| { - generator_layout.variant_fields.iter() - .enumerate() - .flat_map(move |(variant_idx, fields)| { - let variant_idx = Some(VariantIdx::from(variant_idx)); - fields.iter() - .enumerate() - .filter_map(move |(i, field)| { - let decl = &generator_layout. - __local_debuginfo_codegen_only_do_not_use[*field]; - if let Some(name) = decl.name { - let source_info = mir::SourceInfo { - span: decl.source_info.span, - scope: decl.visibility_scope, - }; - Some((variant_idx, i, name, false, source_info)) - } else { - None - } - }) - }) - }).into_iter().flatten(); - - upvars.chain(generator_fields) - }; - - for (variant_idx, field, name, by_ref, source_info) in extra_locals { - let mut projs = env_projs.clone(); - - if let Some(variant_idx) = variant_idx { - projs.push(mir::ProjectionElem::Downcast(None, variant_idx)); - } - - projs.push(mir::ProjectionElem::Field( - mir::Field::new(field), - // HACK(eddyb) field types aren't used or needed here. - tcx.types.err, - )); - - if by_ref { - projs.push(mir::ProjectionElem::Deref); - } - - per_local[env_arg].push(VarDebugInfo { - name, - source_info, - place: mir::Place { - base: mir::PlaceBase::Local(env_arg), - projection: tcx.intern_place_elems(&projs), - }, - }); + for var in &body.var_debug_info { + if let mir::PlaceBase::Local(local) = var.place.base { + per_local[local].push(var); } } - Some(per_local) } else { None } } - -/// Debug information relatating to an user variable. -// FIXME(eddyb) move this to the MIR bodies themselves. -#[derive(Clone)] -pub struct VarDebugInfo<'tcx> { - pub name: Symbol, - - /// Source info of the user variable, including the scope - /// within which the variable is visible (to debuginfo) - /// (see `LocalDecl`'s `source_info` field for more details). - pub source_info: mir::SourceInfo, - - /// Where the data for this user variable is to be found. - pub place: mir::Place<'tcx>, -} diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 5ad1445628..e535aecd63 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -1,7 +1,7 @@ use rustc::ty::{self, Ty, TypeFoldable, Instance}; -use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt}; -use rustc::mir::{self, Body}; -use rustc_target::abi::call::{FnType, PassMode}; +use rustc::ty::layout::{TyLayout, HasTyCtxt, FnAbiExt}; +use rustc::mir; +use rustc_target::abi::call::{FnAbi, PassMode}; use crate::base; use crate::traits::*; @@ -21,7 +21,7 @@ use self::operand::{OperandRef, OperandValue}; pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { instance: Instance<'tcx>, - mir: &'a mir::Body<'tcx>, + mir: mir::ReadOnlyBodyAndCache<'tcx, 'tcx>, debug_context: Option>, @@ -29,7 +29,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { cx: &'a Bx::CodegenCx, - fn_ty: FnType<'tcx, Ty<'tcx>>, + fn_abi: FnAbi<'tcx, Ty<'tcx>>, /// When unwinding is initiated, we have to store this personality /// value somewhere so that we can load it and re-use it in the @@ -74,7 +74,12 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// notably `expect`. locals: IndexVec>, - per_local_var_debug_info: Option>>>, + /// All `VarDebuginfo` from the MIR body, partitioned by `Local`. + /// This is `None` if no variable debuginfo/names are needed. + per_local_var_debug_info: Option>>>, + + /// Caller location propagated if this function has `#[track_caller]`. + caller_location: Option>, } impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { @@ -119,18 +124,18 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, - llfn: Bx::Function, - mir: &'a Body<'tcx>, instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, ) { assert!(!instance.substs.needs_infer()); - let fn_ty = FnType::new(cx, sig, &[]); - debug!("fn_ty: {:?}", fn_ty); + let llfn = cx.get_fn(instance); + + let mir = cx.tcx().instance_mir(instance.def); - let debug_context = - cx.create_function_debug_context(instance, sig, llfn, mir); + let fn_abi = FnAbi::of_instance(cx, instance, &[]); + debug!("fn_abi: {:?}", fn_abi); + + let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); let mut bx = Bx::new_block(cx, llfn, "start"); @@ -153,13 +158,13 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } }).collect(); - let (landing_pads, funclets) = create_funclets(mir, &mut bx, &cleanup_kinds, &block_bxs); - + let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); + let mir_body: &mir::Body<'_> = *mir; let mut fx = FunctionCx { instance, mir, llfn, - fn_ty, + fn_abi, cx, personality_slot: None, blocks: block_bxs, @@ -169,21 +174,22 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( funclets, locals: IndexVec::new(), debug_context, - per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir), + per_local_var_debug_info: debuginfo::per_local_var_debug_info(cx.tcx(), mir_body), + caller_location: None, }; let memory_locals = analyze::non_ssa_locals(&fx); // Allocate variable and temp allocas fx.locals = { - let args = arg_local_refs(&mut bx, &fx, &memory_locals); + let args = arg_local_refs(&mut bx, &mut fx, &memory_locals); let mut allocate_local = |local| { - let decl = &mir.local_decls[local]; + let decl = &mir_body.local_decls[local]; let layout = bx.layout_of(fx.monomorphize(&decl.ty)); assert!(!layout.ty.has_erasable_regions()); - if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() { + if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() { debug!("alloc: {:?} (return place) -> place", local); let llretptr = bx.get_param(0); return LocalRef::Place(PlaceRef::new_sized(llretptr, layout)); @@ -205,7 +211,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let retptr = allocate_local(mir::RETURN_PLACE); iter::once(retptr) .chain(args.into_iter()) - .chain(mir.vars_and_temps_iter().map(allocate_local)) + .chain(mir_body.vars_and_temps_iter().map(allocate_local)) .collect() }; @@ -224,8 +230,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( debug_context.source_locations_enabled = true; } - let rpo = traversal::reverse_postorder(&mir); - let mut visited = BitSet::new_empty(mir.basic_blocks().len()); + let rpo = traversal::reverse_postorder(&mir_body); + let mut visited = BitSet::new_empty(mir_body.basic_blocks().len()); // Codegen the body of each block using reverse postorder for (bb, _) in rpo { @@ -235,7 +241,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Remove blocks that haven't been visited, or have no // predecessors. - for bb in mir.basic_blocks().indices() { + for bb in mir_body.basic_blocks().indices() { // Unreachable block if !visited.contains(bb.index()) { debug!("codegen_mir: block {:?} was not visited", bb); @@ -247,7 +253,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - mir: &'a Body<'tcx>, + mir: &'tcx mir::Body<'tcx>, bx: &mut Bx, cleanup_kinds: &IndexVec, block_bxs: &IndexVec, @@ -318,14 +324,14 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// indirect. fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, - fx: &FunctionCx<'a, 'tcx, Bx>, + fx: &mut FunctionCx<'a, 'tcx, Bx>, memory_locals: &BitSet, ) -> Vec> { let mir = fx.mir; let mut idx = 0; - let mut llarg_idx = fx.fn_ty.ret.is_indirect() as usize; + let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; - mir.args_iter().enumerate().map(|(arg_index, local)| { + let args = mir.args_iter().enumerate().map(|(arg_index, local)| { let arg_decl = &mir.local_decls[local]; if Some(local) == mir.spread_arg { @@ -342,7 +348,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); for i in 0..tupled_arg_tys.len() { - let arg = &fx.fn_ty.args[idx]; + let arg = &fx.fn_abi.args[idx]; idx += 1; if arg.pad.is_some() { llarg_idx += 1; @@ -354,7 +360,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return LocalRef::Place(place); } - if fx.fn_ty.c_variadic && arg_index == fx.fn_ty.args.len() { + if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() { let arg_ty = fx.monomorphize(&arg_decl.ty); let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); @@ -363,7 +369,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return LocalRef::Place(va_list); } - let arg = &fx.fn_ty.args[idx]; + let arg = &fx.fn_abi.args[idx]; idx += 1; if arg.pad.is_some() { llarg_idx += 1; @@ -421,7 +427,27 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx.store_fn_arg(arg, &mut llarg_idx, tmp); LocalRef::Place(tmp) } - }).collect() + }).collect::>(); + + if fx.instance.def.requires_caller_location(bx.tcx()) { + assert_eq!( + fx.fn_abi.args.len(), args.len() + 1, + "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", + ); + + let arg = fx.fn_abi.args.last().unwrap(); + match arg.mode { + PassMode::Direct(_) => (), + _ => bug!("caller location must be PassMode::Direct, found {:?}", arg.mode), + } + + fx.caller_location = Some(OperandRef { + val: OperandValue::Immediate(bx.get_param(llarg_idx)), + layout: arg.layout, + }); + } + + args } mod analyze; diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index ba5e47aeed..a6dec81274 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -1,18 +1,17 @@ -use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; -use rustc::mir; -use rustc::ty; -use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size}; +use super::{FunctionCx, LocalRef}; +use super::place::PlaceRef; -use crate::base; use crate::MemFlags; +use crate::base; use crate::glue; - use crate::traits::*; -use std::fmt; +use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; +use rustc::mir; +use rustc::ty; +use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size}; -use super::{FunctionCx, LocalRef}; -use super::place::PlaceRef; +use std::fmt; /// The representation of a Rust value. The enum variant is in fact /// uniquely determined by the value's type, but is kept as a @@ -75,12 +74,12 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { return OperandRef::new_zst(bx, layout); } - let val = match val.val { - ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"), - ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"), - ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"), - ConstValue::Bound(..) => bug!("encountered a ConstValue::Bound in codegen"), - ConstValue::Placeholder(_) => bug!("encountered a ConstValue::Placeholder in codegen"), + let val_val = match val.val { + ty::ConstKind::Value(val_val) => val_val, + _ => bug!("encountered bad ConstKind in codegen"), + }; + + let val = match val_val { ConstValue::Scalar(x) => { let scalar = match layout.abi { layout::Abi::Scalar(ref x) => x, @@ -343,6 +342,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { } } } + pub fn store_unsized>( self, bx: &mut Bx, @@ -465,8 +465,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Operand::Constant(ref constant) => { - self.eval_mir_constant(constant) - .map(|c| OperandRef::from_const(bx, c)) + self.eval_mir_constant_to_operand(bx, constant) .unwrap_or_else(|err| { match err { // errored or at least linted @@ -476,9 +475,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }, } // Allow RalfJ to sleep soundly knowing that even refactorings that remove - // the above error (or silence it under some conditions) will not cause UB + // the above error (or silence it under some conditions) will not cause UB. bx.abort(); - // We've errored, so we don't have to produce working code. + // We still have to return an operand but it doesn't matter, + // this code is unreachable. let ty = self.monomorphize(&constant.literal.ty); let layout = bx.cx().layout_of(ty); bx.load_operand(PlaceRef::new_sized( diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 3e7c4ef49f..5e13cabced 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -1,28 +1,28 @@ -use rustc::ty::{self, Instance, Ty}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; -use rustc::mir; -use rustc::mir::tcx::PlaceTy; +use super::{FunctionCx, LocalRef}; +use super::operand::OperandValue; + use crate::MemFlags; use crate::common::IntPredicate; use crate::glue; - use crate::traits::*; -use super::{FunctionCx, LocalRef}; -use super::operand::OperandValue; +use rustc::ty::{self, Instance, Ty}; +use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; +use rustc::mir; +use rustc::mir::tcx::PlaceTy; #[derive(Copy, Clone, Debug)] pub struct PlaceRef<'tcx, V> { - /// Pointer to the contents of the place. + /// A pointer to the contents of the place. pub llval: V, - /// This place's extra data if it is unsized, or null. + /// This place's extra data if it is unsized, or `None` if null. pub llextra: Option, - /// Monomorphized type of this place, including variant information. + /// The monomorphized type of this place, including variant information. pub layout: TyLayout<'tcx>, - /// What alignment we know for this place. + /// The alignment we know for this place. pub align: Align, } @@ -107,7 +107,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout) } } - } impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { @@ -334,6 +333,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { variant_index: VariantIdx ) { if self.layout.for_variant(bx.cx(), variant_index).abi.is_uninhabited() { + // We play it safe by using a well-defined `abort`, but we could go for immediate UB + // if that turns out to be helpful. + bx.abort(); return; } match self.layout.variants { @@ -480,17 +482,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = cx.layout_of(self.monomorphize(&ty)); match bx.tcx().const_eval(param_env.and(cid)) { Ok(val) => match val.val { - mir::interpret::ConstValue::ByRef { alloc, offset } => { + ty::ConstKind::Value(mir::interpret::ConstValue::ByRef { + alloc, offset + }) => { bx.cx().from_const_alloc(layout, alloc, offset) } _ => bug!("promoteds should have an allocation: {:?}", val), }, Err(_) => { // This is unreachable as long as runtime - // and compile-time agree on values + // and compile-time agree perfectly. // With floats that won't always be true, - // so we generate an abort. + // so we generate a (safe) abort. bx.abort(); + // We still have to return a place but it doesn't matter, + // this code is unreachable. let llval = bx.cx().const_undef( bx.cx().type_ptr_to(bx.cx().backend_type(layout)) ); @@ -559,7 +565,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llindex = bx.sub(lllen, lloffset); cg_base.project_index(bx, llindex) } - mir::ProjectionElem::Subslice { from, to } => { + mir::ProjectionElem::Subslice { from, to, from_end } => { let mut subslice = cg_base.project_index(bx, bx.cx().const_usize(*from as u64)); let projected_ty = PlaceTy::from_ty(cg_base.layout.ty) @@ -567,6 +573,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty)); if subslice.layout.is_unsized() { + assert!(from_end, "slice subslices should be `from_end`"); subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(), bx.cx().const_usize((*from as u64) + (*to as u64)))); } @@ -590,7 +597,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn monomorphized_place_ty(&self, place_ref: &mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); - let place_ty = mir::Place::ty_from(place_ref.base, place_ref.projection, self.mir, tcx); + let place_ty = mir::Place::ty_from( + place_ref.base, + place_ref.projection, + *self.mir, + tcx, + ); self.monomorphize(&place_ty.ty) } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 1608f222bc..488ae8dbf9 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -1,22 +1,22 @@ +use super::{FunctionCx, LocalRef}; +use super::operand::{OperandRef, OperandValue}; +use super::place::PlaceRef; + +use crate::base; +use crate::MemFlags; +use crate::common::{self, RealPredicate, IntPredicate}; +use crate::traits::*; + use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc::mir; use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc_apfloat::{ieee, Float, Status, Round}; -use std::{u128, i128}; use syntax::symbol::sym; use syntax::source_map::{DUMMY_SP, Span}; -use crate::base; -use crate::MemFlags; -use crate::common::{self, RealPredicate, IntPredicate}; - -use crate::traits::*; - -use super::{FunctionCx, LocalRef}; -use super::operand::{OperandRef, OperandValue}; -use super::place::PlaceRef; +use std::{u128, i128}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_rvalue( @@ -31,8 +31,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match *rvalue { mir::Rvalue::Use(ref operand) => { let cg_operand = self.codegen_operand(&mut bx, operand); - // FIXME: consider not copying constants through stack. (fixable by codegenning - // constants into OperandValue::Ref, why don’t we do that yet if we don’t?) + // FIXME: consider not copying constants through stack. (Fixable by codegen'ing + // constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?) cg_operand.val.store(&mut bx, dest); bx } @@ -41,7 +41,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The destination necessarily contains a fat pointer, so if // it's a scalar pair, it's a fat pointer or newtype thereof. if bx.cx().is_backend_scalar_pair(dest.layout) { - // into-coerce of a thin pointer to a fat pointer - just + // Into-coerce of a thin pointer to a fat pointer -- just // use the operand path. let (mut bx, temp) = self.codegen_rvalue_operand(bx, rvalue); temp.val.store(&mut bx, dest); @@ -56,10 +56,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match operand.val { OperandValue::Pair(..) | OperandValue::Immediate(_) => { - // unsize from an immediate structure. We don't + // Unsize from an immediate structure. We don't // really need a temporary alloca here, but // avoiding it would require us to have - // `coerce_unsized_into` use extractvalue to + // `coerce_unsized_into` use `extractvalue` to // index into the struct, and this case isn't // important enough for it. debug!("codegen_rvalue: creating ugly alloca"); @@ -74,7 +74,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { base::coerce_unsized_into(&mut bx, source, dest); } OperandValue::Ref(_, Some(_), _) => { - bug!("unsized coercion on an unsized rvalue") + bug!("unsized coercion on an unsized rvalue"); } } bx @@ -160,7 +160,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx } - _ => bug!("unsized assignment other than Rvalue::Use"), + _ => bug!("unsized assignment other than `Rvalue::Use`"), } } @@ -220,17 +220,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => { - // this is a no-op at the LLVM level + // This is a no-op at the LLVM level. operand.val } mir::CastKind::Pointer(PointerCast::Unsize) => { assert!(bx.cx().is_backend_scalar_pair(cast)); match operand.val { OperandValue::Pair(lldata, llextra) => { - // unsize from a fat pointer - this is a + // unsize from a fat pointer -- this is a // "trait-object-to-supertrait" coercion, for - // example, - // &'a fmt::Debug+Send => &'a fmt::Debug, + // example, `&'a fmt::Debug + Send => &'a fmt::Debug`. // HACK(eddyb) have to bitcast pointers // until LLVM removes pointee types. @@ -245,13 +244,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Pair(lldata, llextra) } OperandValue::Ref(..) => { - bug!("by-ref operand {:?} in codegen_rvalue_operand", + bug!("by-ref operand {:?} in `codegen_rvalue_operand`", operand); } } } - mir::CastKind::Pointer(PointerCast::MutToConstPointer) - | mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => { + mir::CastKind::Pointer(PointerCast::MutToConstPointer) | + mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => { if let OperandValue::Pair(data_ptr, meta) = operand.val { if bx.cx().is_backend_scalar_pair(cast) { let data_cast = bx.pointercast(data_ptr, @@ -265,11 +264,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Immediate(llval) } } else { - bug!("Unexpected non-Pair operand") + bug!("unexpected non-pair operand"); } } - mir::CastKind::Pointer(PointerCast::MutToConstPointer) - | mir::CastKind::Misc => { + mir::CastKind::Pointer(PointerCast::MutToConstPointer) | + mir::CastKind::Pointer(PointerCast::ArrayToPointer) | + mir::CastKind::Misc => { assert!(bx.cx().is_backend_immediate(cast)); let ll_t_out = bx.cx().immediate_backend_type(cast); if operand.layout.abi.is_uninhabited() { @@ -460,7 +460,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Discriminant(ref place) => { - let discr_ty = rvalue.ty(&*self.mir, bx.tcx()); + let discr_ty = rvalue.ty(*self.mir, bx.tcx()); let discr = self.codegen_place(&mut bx, &place.as_ref()) .codegen_get_discr(&mut bx, discr_ty); (bx, OperandRef { @@ -513,7 +513,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Aggregate(..) => { // According to `rvalue_creates_operand`, only ZST // aggregate rvalues are allowed to be operands. - let ty = rvalue.ty(self.mir, self.cx.tcx()); + let ty = rvalue.ty(*self.mir, self.cx.tcx()); let operand = OperandRef::new_zst( &mut bx, self.cx.layout_of(self.monomorphize(&ty)), @@ -710,7 +710,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { true, mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => { - let ty = rvalue.ty(self.mir, self.cx.tcx()); + let ty = rvalue.ty(*self.mir, self.cx.tcx()); let ty = self.monomorphize(&ty); self.cx.spanned_layout_of(ty, span).is_zst() } diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index d11601be0b..0b82edea15 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -6,6 +6,8 @@ use super::LocalRef; use super::OperandValue; use crate::traits::*; +use rustc_error_codes::*; + impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_statement( &mut self, diff --git a/src/librustc_codegen_ssa/traits/abi.rs b/src/librustc_codegen_ssa/traits/abi.rs index 509255c37b..fb44a69ce0 100644 --- a/src/librustc_codegen_ssa/traits/abi.rs +++ b/src/librustc_codegen_ssa/traits/abi.rs @@ -1,8 +1,8 @@ use super::BackendTypes; use rustc::ty::{Ty}; -use rustc_target::abi::call::FnType; +use rustc_target::abi::call::FnAbi; pub trait AbiBuilderMethods<'tcx>: BackendTypes { - fn apply_attrs_callsite(&mut self, ty: &FnType<'tcx, Ty<'tcx>>, callsite: Self::Value); + fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value); fn get_param(&self, index: usize) -> Self::Value; } diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs index c9e1ed86e9..612bce2d95 100644 --- a/src/librustc_codegen_ssa/traits/asm.rs +++ b/src/librustc_codegen_ssa/traits/asm.rs @@ -1,13 +1,13 @@ use super::BackendTypes; use crate::mir::place::PlaceRef; -use rustc::hir::{GlobalAsm, InlineAsm}; +use rustc::hir::{GlobalAsm, InlineAsmInner}; use syntax_pos::Span; pub trait AsmBuilderMethods<'tcx>: BackendTypes { /// Take an inline assembly expression and splat it out via LLVM fn codegen_inline_asm( &mut self, - ia: &InlineAsm, + ia: &InlineAsmInner, outputs: Vec>, inputs: Vec, span: Span, diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 8ab8243afd..cfaa675626 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -1,17 +1,18 @@ -use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout}; -use rustc::ty::Ty; - use super::write::WriteBackendMethods; use super::CodegenObject; + +use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout}; +use rustc::ty::Ty; use rustc::middle::cstore::EncodedMetadata; use rustc::session::{Session, config}; use rustc::ty::TyCtxt; use rustc_codegen_utils::codegen_backend::CodegenBackend; -use std::sync::Arc; -use std::sync::mpsc; use syntax::expand::allocator::AllocatorKind; use syntax_pos::symbol::Symbol; +use std::sync::Arc; +use std::sync::mpsc; + pub trait BackendTypes { type Value: CodegenObject; type Function: CodegenObject; diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 62b5bcbb6c..31044d4eb4 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -2,16 +2,19 @@ use super::abi::AbiBuilderMethods; use super::asm::AsmBuilderMethods; use super::debuginfo::DebugInfoBuilderMethods; use super::intrinsic::IntrinsicCallMethods; -use super::type_::ArgTypeMethods; +use super::type_::ArgAbiMethods; use super::{HasCodegen, StaticBuilderMethods}; + use crate::common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope}; use crate::mir::operand::OperandRef; use crate::mir::place::PlaceRef; use crate::MemFlags; + use rustc::ty::Ty; use rustc::ty::layout::{Align, Size, HasParamEnv}; -use rustc_target::spec::{HasTargetSpec}; +use rustc_target::spec::HasTargetSpec; + use std::ops::Range; use std::iter::TrustedLen; @@ -25,7 +28,7 @@ pub enum OverflowOp { pub trait BuilderMethods<'a, 'tcx>: HasCodegen<'tcx> + DebugInfoBuilderMethods<'tcx> - + ArgTypeMethods<'tcx> + + ArgAbiMethods<'tcx> + AbiBuilderMethods<'tcx> + IntrinsicCallMethods<'tcx> + AsmBuilderMethods<'tcx> diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs index 802eaaa357..e67201b710 100644 --- a/src/librustc_codegen_ssa/traits/debuginfo.rs +++ b/src/librustc_codegen_ssa/traits/debuginfo.rs @@ -2,8 +2,9 @@ use super::BackendTypes; use crate::mir::debuginfo::{FunctionDebugContext, VariableKind}; use rustc::hir::def_id::CrateNum; use rustc::mir; -use rustc::ty::{self, Ty, Instance}; +use rustc::ty::{Ty, Instance}; use rustc::ty::layout::Size; +use rustc_target::abi::call::FnAbi; use syntax::ast::Name; use syntax_pos::{SourceFile, Span}; @@ -17,7 +18,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes { fn create_function_debug_context( &self, instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Function, mir: &mir::Body<'_>, ) -> Option>; diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs index cd42044e48..1dd2c74dd4 100644 --- a/src/librustc_codegen_ssa/traits/declare.rs +++ b/src/librustc_codegen_ssa/traits/declare.rs @@ -1,7 +1,8 @@ use super::BackendTypes; use rustc::hir::def_id::DefId; use rustc::mir::mono::{Linkage, Visibility}; -use rustc::ty::{self, Instance}; +use rustc::ty::{Instance, Ty}; +use rustc_target::abi::call::FnAbi; pub trait DeclareMethods<'tcx>: BackendTypes { /// Declare a global value. @@ -23,7 +24,7 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Function; + fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function; /// Declare a global with an intention to define it. /// @@ -38,20 +39,6 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// Use this function when you intend to define a global without a name. fn define_private_global(&self, ty: Self::Type) -> Self::Value; - /// Declare a Rust function with an intention to define it. - /// - /// Use this function when you intend to define a function. This function will - /// return panic if the name already has a definition associated with it. This - /// can happen with #[no_mangle] or #[export_name], for example. - fn define_fn(&self, name: &str, fn_sig: ty::PolyFnSig<'tcx>) -> Self::Value; - - /// Declare a Rust function with an intention to define it. - /// - /// Use this function when you intend to define a function. This function will - /// return panic if the name already has a definition associated with it. This - /// can happen with #[no_mangle] or #[export_name], for example. - fn define_internal_fn(&self, name: &str, fn_sig: ty::PolyFnSig<'tcx>) -> Self::Value; - /// Gets declared value by name. fn get_declared_value(&self, name: &str) -> Option; diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index 2c484084c4..8006d778bd 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -1,7 +1,7 @@ use super::BackendTypes; use crate::mir::operand::OperandRef; use rustc::ty::{self, Ty}; -use rustc_target::abi::call::FnType; +use rustc_target::abi::call::FnAbi; use syntax_pos::Span; pub trait IntrinsicCallMethods<'tcx>: BackendTypes { @@ -11,7 +11,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn codegen_intrinsic_call( &mut self, instance: ty::Instance<'tcx>, - fn_ty: &FnType<'tcx, Ty<'tcx>>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Self::Value>], llresult: Self::Value, span: Span, diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 4318ef1649..9b673de8b0 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -38,12 +38,12 @@ pub use self::intrinsic::IntrinsicCallMethods; pub use self::misc::MiscMethods; pub use self::statics::{StaticMethods, StaticBuilderMethods}; pub use self::type_::{ - ArgTypeMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods, + ArgAbiMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods, }; pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods}; -use rustc::ty::layout::{HasParamEnv, HasTyCtxt}; -use rustc_target::spec::{HasTargetSpec}; +use rustc::ty::layout::{HasParamEnv, HasTyCtxt}; +use rustc_target::spec::HasTargetSpec; use std::fmt; diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs index 19d41c6b37..f074d4479f 100644 --- a/src/librustc_codegen_ssa/traits/type_.rs +++ b/src/librustc_codegen_ssa/traits/type_.rs @@ -5,7 +5,7 @@ use crate::common::TypeKind; use crate::mir::place::PlaceRef; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, TyLayout}; -use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg}; +use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; use syntax_pos::DUMMY_SP; // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use @@ -96,7 +96,7 @@ impl DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscM pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { fn backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type; fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type; - fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> Self::Type; + fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type; fn reg_backend_type(&self, ty: &Reg) -> Self::Type; fn immediate_backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type; fn is_backend_immediate(&self, layout: TyLayout<'tcx>) -> bool; @@ -110,20 +110,20 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { ) -> Self::Type; } -pub trait ArgTypeMethods<'tcx>: HasCodegen<'tcx> { +pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> { fn store_fn_arg( &mut self, - ty: &ArgType<'tcx, Ty<'tcx>>, + arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, idx: &mut usize, dst: PlaceRef<'tcx, Self::Value>, ); - fn store_arg_ty( + fn store_arg( &mut self, - ty: &ArgType<'tcx, Ty<'tcx>>, + arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, val: Self::Value, dst: PlaceRef<'tcx, Self::Value>, ); - fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> Self::Type; + fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type; } pub trait TypeMethods<'tcx>: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 66920342ff..fb2099e71a 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -19,7 +19,7 @@ extern crate rustc; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::hir::def_id::LOCAL_CRATE; +use rustc::hir::def_id::{LOCAL_CRATE, DefId}; use syntax::symbol::sym; pub mod link; @@ -27,18 +27,50 @@ pub mod codegen_backend; pub mod symbol_names; pub mod symbol_names_test; + +pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: DefId) { + tcx.sess.delay_span_bug( + tcx.def_span(key), + "delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]" + ); +} + /// check for the #[rustc_error] annotation, which forces an /// error in codegen. This is used to write compile-fail tests /// that actually test that compilation succeeds without /// reporting an error. pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) { - if tcx.has_attr(def_id, sym::rustc_error) { - tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful"); + let attrs = &*tcx.get_attrs(def_id); + for attr in attrs { + if attr.check_name(sym::rustc_error) { + match attr.meta_item_list() { + // check if there is a #[rustc_error(delayed)] + Some(list) => { + if list.iter().any(|list_item| { + list_item.ident().map(|i| i.name) == + Some(sym::delay_span_bug_from_inside_query) + }) { + tcx.ensure().trigger_delay_span_bug(def_id); + } + } + // bare #[rustc_error] + None => { + tcx.sess.span_fatal( + tcx.def_span(def_id), + "fatal error triggered by #[rustc_error]" + ); + } + } + } } } } pub fn provide(providers: &mut Providers<'_>) { crate::symbol_names::provide(providers); + *providers = Providers { + trigger_delay_span_bug, + ..*providers + }; } diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs index 601a33a66b..1597f98771 100644 --- a/src/librustc_codegen_utils/symbol_names/legacy.rs +++ b/src/librustc_codegen_utils/symbol_names/legacy.rs @@ -121,9 +121,10 @@ fn get_symbol_hash<'tcx>( substs.hash_stable(&mut hcx, &mut hasher); if let Some(instantiating_crate) = instantiating_crate { - (&tcx.original_crate_name(instantiating_crate).as_str()[..]) + tcx.original_crate_name(instantiating_crate).as_str() + .hash_stable(&mut hcx, &mut hasher); + tcx.crate_disambiguator(instantiating_crate) .hash_stable(&mut hcx, &mut hasher); - (&tcx.crate_disambiguator(instantiating_crate)).hash_stable(&mut hcx, &mut hasher); } // We want to avoid accidental collision between different types of instances. @@ -252,7 +253,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { ct: &'tcx ty::Const<'tcx>, ) -> Result { // only print integers - if let ConstValue::Scalar(Scalar::Raw { .. }) = ct.val { + if let ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { .. })) = ct.val { if ct.ty.is_integral() { return self.pretty_print_const(ct); } diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 55b148fceb..1dfcc21f39 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -373,8 +373,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::Ref(r, ty, mutbl) => { self.push(match mutbl { - hir::MutImmutable => "R", - hir::MutMutable => "Q", + hir::Mutability::Immutable => "R", + hir::Mutability::Mutable => "Q", }); if *r != ty::ReErased { self = r.print(self)?; @@ -384,8 +384,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::RawPtr(mt) => { self.push(match mt.mutbl { - hir::MutImmutable => "P", - hir::MutMutable => "O", + hir::Mutability::Immutable => "P", + hir::Mutability::Mutable => "O", }); self = mt.ty.print(self)?; } @@ -601,8 +601,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::Misc | DefPathData::Impl | DefPathData::MacroNs(_) - | DefPathData::LifetimeNs(_) - | DefPathData::GlobalMetaData(_) => { + | DefPathData::LifetimeNs(_) => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) } }; diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 065c8436ae..7fa40b8a86 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -23,8 +23,10 @@ stable_deref_trait = "1.0.0" rayon = { version = "0.3.0", package = "rustc-rayon" } rayon-core = { version = "0.3.0", package = "rustc-rayon-core" } rustc-hash = "1.0.1" -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_index = { path = "../librustc_index", package = "rustc_index" } +bitflags = "1.2.1" +measureme = "0.5" [dependencies.parking_lot] version = "0.9" diff --git a/src/librustc_data_structures/flock.rs b/src/librustc_data_structures/flock.rs index b0bd137f2c..01f25a054f 100644 --- a/src/librustc_data_structures/flock.rs +++ b/src/librustc_data_structures/flock.rs @@ -298,15 +298,3 @@ cfg_if! { } } } - -impl Lock { - pub fn panicking_new(p: &Path, - wait: bool, - create: bool, - exclusive: bool) - -> Lock { - Lock::new(p, wait, create, exclusive).unwrap_or_else(|err| { - panic!("could not lock `{}`: {}", p.display(), err); - }) - } -} diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs index 444463c08e..5fb58eea38 100644 --- a/src/librustc_data_structures/graph/dominators/mod.rs +++ b/src/librustc_data_structures/graph/dominators/mod.rs @@ -7,32 +7,33 @@ use rustc_index::vec::{Idx, IndexVec}; use super::iterate::reverse_post_order; use super::ControlFlowGraph; +use std::borrow::BorrowMut; #[cfg(test)] mod tests; -pub fn dominators(graph: &G) -> Dominators { +pub fn dominators(graph: G) -> Dominators { let start_node = graph.start_node(); - let rpo = reverse_post_order(graph, start_node); + let rpo = reverse_post_order(&graph, start_node); dominators_given_rpo(graph, &rpo) } -fn dominators_given_rpo( - graph: &G, +fn dominators_given_rpo>( + mut graph: G, rpo: &[G::Node], ) -> Dominators { - let start_node = graph.start_node(); + let start_node = graph.borrow().start_node(); assert_eq!(rpo[0], start_node); // compute the post order index (rank) for each node let mut post_order_rank: IndexVec = - (0..graph.num_nodes()).map(|_| 0).collect(); + (0..graph.borrow().num_nodes()).map(|_| 0).collect(); for (index, node) in rpo.iter().rev().cloned().enumerate() { post_order_rank[node] = index; } let mut immediate_dominators: IndexVec> = - (0..graph.num_nodes()).map(|_| None).collect(); + (0..graph.borrow().num_nodes()).map(|_| None).collect(); immediate_dominators[start_node] = Some(start_node); let mut changed = true; @@ -41,7 +42,7 @@ fn dominators_given_rpo( for &node in &rpo[1..] { let mut new_idom = None; - for pred in graph.predecessors(node) { + for pred in graph.borrow_mut().predecessors(node) { if immediate_dominators[pred].is_some() { // (*) dominators for `pred` have been calculated new_idom = Some(if let Some(new_idom) = new_idom { diff --git a/src/librustc_data_structures/jobserver.rs b/src/librustc_data_structures/jobserver.rs index b42ccb932b..a811c88839 100644 --- a/src/librustc_data_structures/jobserver.rs +++ b/src/librustc_data_structures/jobserver.rs @@ -1,4 +1,4 @@ -use jobserver_crate::Client; +pub use jobserver_crate::Client; use lazy_static::lazy_static; lazy_static! { diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 474a42644d..fb541637e5 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -94,6 +94,7 @@ pub use ena::unify; pub mod vec_linked_list; pub mod work_queue; pub mod fingerprint; +pub mod profiling; pub struct OnDrop(pub F); diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 958ab617cb..974d9dcfae 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -85,19 +85,20 @@ mod graphviz; #[cfg(test)] mod tests; -pub trait ForestObligation : Clone + Debug { - type Predicate : Clone + hash::Hash + Eq + Debug; +pub trait ForestObligation: Clone + Debug { + type Predicate: Clone + hash::Hash + Eq + Debug; fn as_predicate(&self) -> &Self::Predicate; } pub trait ObligationProcessor { - type Obligation : ForestObligation; - type Error : Debug; + type Obligation: ForestObligation; + type Error: Debug; - fn process_obligation(&mut self, - obligation: &mut Self::Obligation) - -> ProcessResult; + fn process_obligation( + &mut self, + obligation: &mut Self::Obligation, + ) -> ProcessResult; /// As we do the cycle check, we invoke this callback when we /// encounter an actual cycle. `cycle` is an iterator that starts @@ -107,10 +108,9 @@ pub trait ObligationProcessor { /// In other words, if we had O1 which required O2 which required /// O3 which required O1, we would give an iterator yielding O1, /// O2, O3 (O1 is not yielded twice). - fn process_backedge<'c, I>(&mut self, - cycle: I, - _marker: PhantomData<&'c Self::Obligation>) - where I: Clone + Iterator; + fn process_backedge<'c, I>(&mut self, cycle: I, _marker: PhantomData<&'c Self::Obligation>) + where + I: Clone + Iterator; } /// The result type used by `process_obligation`. @@ -128,19 +128,13 @@ type ObligationTreeIdGenerator = ::std::iter::Map<::std::ops::RangeFrom, fn(usize) -> ObligationTreeId>; pub struct ObligationForest { - /// The list of obligations. In between calls to - /// `process_obligations`, this list only contains nodes in the - /// `Pending` or `Success` state (with a non-zero number of - /// incomplete children). During processing, some of those nodes - /// may be changed to the error state, or we may find that they - /// are completed (That is, `num_incomplete_children` drops to 0). - /// At the end of processing, those nodes will be removed by a - /// call to `compress`. + /// The list of obligations. In between calls to `process_obligations`, + /// this list only contains nodes in the `Pending` or `Waiting` state. /// /// `usize` indices are used here and throughout this module, rather than - /// `rustc_index::newtype_index!` indices, because this code is hot enough that the - /// `u32`-to-`usize` conversions that would be required are significant, - /// and space considerations are not important. + /// `rustc_index::newtype_index!` indices, because this code is hot enough + /// that the `u32`-to-`usize` conversions that would be required are + /// significant, and space considerations are not important. nodes: Vec>, /// A cache of predicates that have been successfully completed. @@ -187,52 +181,69 @@ struct Node { } impl Node { - fn new( - parent: Option, - obligation: O, - obligation_tree_id: ObligationTreeId - ) -> Node { + fn new(parent: Option, obligation: O, obligation_tree_id: ObligationTreeId) -> Node { Node { obligation, state: Cell::new(NodeState::Pending), - dependents: - if let Some(parent_index) = parent { - vec![parent_index] - } else { - vec![] - }, + dependents: if let Some(parent_index) = parent { vec![parent_index] } else { vec![] }, has_parent: parent.is_some(), obligation_tree_id, } } } -/// The state of one node in some tree within the forest. This -/// represents the current state of processing for the obligation (of -/// type `O`) associated with this node. +/// The state of one node in some tree within the forest. This represents the +/// current state of processing for the obligation (of type `O`) associated +/// with this node. /// -/// Outside of ObligationForest methods, nodes should be either Pending -/// or Waiting. +/// The non-`Error` state transitions are as follows. +/// ``` +/// (Pre-creation) +/// | +/// | register_obligation_at() (called by process_obligations() and +/// v from outside the crate) +/// Pending +/// | +/// | process_obligations() +/// v +/// Success +/// | ^ +/// | | mark_successes() +/// | v +/// | Waiting +/// | +/// | process_cycles() +/// v +/// Done +/// | +/// | compress() +/// v +/// (Removed) +/// ``` +/// The `Error` state can be introduced in several places, via `error_at()`. +/// +/// Outside of `ObligationForest` methods, nodes should be either `Pending` or +/// `Waiting`. #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum NodeState { - /// Obligations for which selection had not yet returned a - /// non-ambiguous result. + /// This obligation has not yet been selected successfully. Cannot have + /// subobligations. Pending, - /// This obligation was selected successfully, but may or - /// may not have subobligations. + /// This obligation was selected successfully, but may or may not have + /// subobligations. Success, - /// This obligation was selected successfully, but it has - /// a pending subobligation. + /// This obligation was selected successfully, but it has a pending + /// subobligation. Waiting, - /// This obligation, along with its subobligations, are complete, - /// and will be removed in the next collection. + /// This obligation, along with its subobligations, are complete, and will + /// be removed in the next collection. Done, - /// This obligation was resolved to an error. Error nodes are - /// removed from the vector by the compression step. + /// This obligation was resolved to an error. It will be removed by the + /// next compression step. Error, } @@ -300,10 +311,7 @@ impl ObligationForest { match self.active_cache.entry(obligation.as_predicate().clone()) { Entry::Occupied(o) => { - let index = *o.get(); - debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!", - obligation, parent, index); - let node = &mut self.nodes[index]; + let node = &mut self.nodes[*o.get()]; if let Some(parent_index) = parent { // If the node is already in `active_cache`, it has already // had its chance to be marked with a parent. So if it's @@ -313,27 +321,20 @@ impl ObligationForest { node.dependents.push(parent_index); } } - if let NodeState::Error = node.state.get() { - Err(()) - } else { - Ok(()) - } + if let NodeState::Error = node.state.get() { Err(()) } else { Ok(()) } } Entry::Vacant(v) => { - debug!("register_obligation_at({:?}, {:?}) - ok, new index is {}", - obligation, parent, self.nodes.len()); - let obligation_tree_id = match parent { Some(parent_index) => self.nodes[parent_index].obligation_tree_id, None => self.obligation_tree_id_generator.next().unwrap(), }; - let already_failed = - parent.is_some() - && self.error_cache - .get(&obligation_tree_id) - .map(|errors| errors.contains(obligation.as_predicate())) - .unwrap_or(false); + let already_failed = parent.is_some() + && self + .error_cache + .get(&obligation_tree_id) + .map(|errors| errors.contains(obligation.as_predicate())) + .unwrap_or(false); if already_failed { Err(()) @@ -349,14 +350,12 @@ impl ObligationForest { /// Converts all remaining obligations to the given error. pub fn to_errors(&mut self, error: E) -> Vec> { - let errors = self.nodes.iter().enumerate() + let errors = self + .nodes + .iter() + .enumerate() .filter(|(_index, node)| node.state.get() == NodeState::Pending) - .map(|(index, _node)| { - Error { - error: error.clone(), - backtrace: self.error_at(index), - } - }) + .map(|(index, _node)| Error { error: error.clone(), backtrace: self.error_at(index) }) .collect(); let successful_obligations = self.compress(DoCompleted::Yes); @@ -366,9 +365,11 @@ impl ObligationForest { /// Returns the set of obligations that are in a pending state. pub fn map_pending_obligations(&self, f: F) -> Vec

- where F: Fn(&O) -> P + where + F: Fn(&O) -> P, { - self.nodes.iter() + self.nodes + .iter() .filter(|node| node.state.get() == NodeState::Pending) .map(|node| f(&node.obligation)) .collect() @@ -386,33 +387,40 @@ impl ObligationForest { /// be called in a loop until `outcome.stalled` is false. /// /// This _cannot_ be unrolled (presently, at least). - pub fn process_obligations

(&mut self, processor: &mut P, do_completed: DoCompleted) - -> Outcome - where P: ObligationProcessor + pub fn process_obligations

( + &mut self, + processor: &mut P, + do_completed: DoCompleted, + ) -> Outcome + where + P: ObligationProcessor, { - debug!("process_obligations(len={})", self.nodes.len()); - let mut errors = vec![]; let mut stalled = true; - for index in 0..self.nodes.len() { + // Note that the loop body can append new nodes, and those new nodes + // will then be processed by subsequent iterations of the loop. + // + // We can't use an iterator for the loop because `self.nodes` is + // appended to and the borrow checker would complain. We also can't use + // `for index in 0..self.nodes.len() { ... }` because the range would + // be computed with the initial length, and we would miss the appended + // nodes. Therefore we use a `while` loop. + let mut index = 0; + while index < self.nodes.len() { let node = &mut self.nodes[index]; - debug!("process_obligations: node {} == {:?}", index, node); - // `processor.process_obligation` can modify the predicate within // `node.obligation`, and that predicate is the key used for // `self.active_cache`. This means that `self.active_cache` can get // out of sync with `nodes`. It's not very common, but it does // happen, and code in `compress` has to allow for it. if node.state.get() != NodeState::Pending { + index += 1; continue; } - let result = processor.process_obligation(&mut node.obligation); - - debug!("process_obligations: node {} got result {:?}", index, result); - match result { + match processor.process_obligation(&mut node.obligation) { ProcessResult::Unchanged => { // No change in state. } @@ -422,10 +430,7 @@ impl ObligationForest { node.state.set(NodeState::Success); for child in children { - let st = self.register_obligation_at( - child, - Some(index) - ); + let st = self.register_obligation_at(child, Some(index)); if let Err(()) = st { // Error already reported - propagate it // to our node. @@ -435,12 +440,10 @@ impl ObligationForest { } ProcessResult::Error(err) => { stalled = false; - errors.push(Error { - error: err, - backtrace: self.error_at(index), - }); + errors.push(Error { error: err, backtrace: self.error_at(index) }); } } + index += 1; } if stalled { @@ -453,67 +456,11 @@ impl ObligationForest { }; } - self.mark_as_waiting(); + self.mark_successes(); self.process_cycles(processor); let completed = self.compress(do_completed); - debug!("process_obligations: complete"); - - Outcome { - completed, - errors, - stalled, - } - } - - /// Mark all `NodeState::Success` nodes as `NodeState::Done` and - /// report all cycles between them. This should be called - /// after `mark_as_waiting` marks all nodes with pending - /// subobligations as NodeState::Waiting. - fn process_cycles

(&self, processor: &mut P) - where P: ObligationProcessor - { - let mut stack = vec![]; - - debug!("process_cycles()"); - - for (index, node) in self.nodes.iter().enumerate() { - // For some benchmarks this state test is extremely - // hot. It's a win to handle the no-op cases immediately to avoid - // the cost of the function call. - if node.state.get() == NodeState::Success { - self.find_cycles_from_node(&mut stack, processor, index); - } - } - - debug!("process_cycles: complete"); - - debug_assert!(stack.is_empty()); - } - - fn find_cycles_from_node

(&self, stack: &mut Vec, processor: &mut P, index: usize) - where P: ObligationProcessor - { - let node = &self.nodes[index]; - if node.state.get() == NodeState::Success { - match stack.iter().rposition(|&n| n == index) { - None => { - stack.push(index); - for &index in node.dependents.iter() { - self.find_cycles_from_node(stack, processor, index); - } - stack.pop(); - node.state.set(NodeState::Done); - } - Some(rpos) => { - // Cycle detected. - processor.process_backedge( - stack[rpos..].iter().map(GetObligation(&self.nodes)), - PhantomData - ); - } - } - } + Outcome { completed, errors, stalled } } /// Returns a vector of obligations for `p` and all of its @@ -549,53 +496,97 @@ impl ObligationForest { trace } + /// Mark all `Waiting` nodes as `Success`, except those that depend on a + /// pending node. + fn mark_successes(&self) { + // Convert all `Waiting` nodes to `Success`. + for node in &self.nodes { + if node.state.get() == NodeState::Waiting { + node.state.set(NodeState::Success); + } + } + + // Convert `Success` nodes that depend on a pending node back to + // `Waiting`. + for node in &self.nodes { + if node.state.get() == NodeState::Pending { + // This call site is hot. + self.inlined_mark_dependents_as_waiting(node); + } + } + } + // This always-inlined function is for the hot call site. #[inline(always)] - fn inlined_mark_neighbors_as_waiting_from(&self, node: &Node) { + fn inlined_mark_dependents_as_waiting(&self, node: &Node) { for &index in node.dependents.iter() { let node = &self.nodes[index]; - match node.state.get() { - NodeState::Waiting | NodeState::Error => {} - NodeState::Success => { - node.state.set(NodeState::Waiting); - // This call site is cold. - self.uninlined_mark_neighbors_as_waiting_from(node); - } - NodeState::Pending | NodeState::Done => { - // This call site is cold. - self.uninlined_mark_neighbors_as_waiting_from(node); - } + let state = node.state.get(); + if state == NodeState::Success { + node.state.set(NodeState::Waiting); + // This call site is cold. + self.uninlined_mark_dependents_as_waiting(node); + } else { + debug_assert!(state == NodeState::Waiting || state == NodeState::Error) } } } // This never-inlined function is for the cold call site. #[inline(never)] - fn uninlined_mark_neighbors_as_waiting_from(&self, node: &Node) { - self.inlined_mark_neighbors_as_waiting_from(node) + fn uninlined_mark_dependents_as_waiting(&self, node: &Node) { + self.inlined_mark_dependents_as_waiting(node) } - /// Marks all nodes that depend on a pending node as `NodeState::Waiting`. - fn mark_as_waiting(&self) { - for node in &self.nodes { - if node.state.get() == NodeState::Waiting { - node.state.set(NodeState::Success); + /// Report cycles between all `Success` nodes, and convert all `Success` + /// nodes to `Done`. This must be called after `mark_successes`. + fn process_cycles

(&self, processor: &mut P) + where + P: ObligationProcessor, + { + let mut stack = vec![]; + + for (index, node) in self.nodes.iter().enumerate() { + // For some benchmarks this state test is extremely hot. It's a win + // to handle the no-op cases immediately to avoid the cost of the + // function call. + if node.state.get() == NodeState::Success { + self.find_cycles_from_node(&mut stack, processor, index); } } - for node in &self.nodes { - if node.state.get() == NodeState::Pending { - // This call site is hot. - self.inlined_mark_neighbors_as_waiting_from(node); + debug_assert!(stack.is_empty()); + } + + fn find_cycles_from_node

(&self, stack: &mut Vec, processor: &mut P, index: usize) + where + P: ObligationProcessor, + { + let node = &self.nodes[index]; + if node.state.get() == NodeState::Success { + match stack.iter().rposition(|&n| n == index) { + None => { + stack.push(index); + for &dep_index in node.dependents.iter() { + self.find_cycles_from_node(stack, processor, dep_index); + } + stack.pop(); + node.state.set(NodeState::Done); + } + Some(rpos) => { + // Cycle detected. + processor.process_backedge( + stack[rpos..].iter().map(GetObligation(&self.nodes)), + PhantomData, + ); + } } } } /// Compresses the vector, removing all popped nodes. This adjusts the - /// indices and hence invalidates any outstanding indices. - /// - /// Beforehand, all nodes must be marked as `Done` and no cycles - /// on these nodes may be present. This is done by e.g., `process_cycles`. + /// indices and hence invalidates any outstanding indices. `process_cycles` + /// must be run beforehand to remove any cycles on `Success` nodes. #[inline(never)] fn compress(&mut self, do_completed: DoCompleted) -> Option> { let orig_nodes_len = self.nodes.len(); @@ -605,8 +596,8 @@ impl ObligationForest { let mut dead_nodes = 0; let mut removed_done_obligations: Vec = vec![]; - // Now move all Done/Error nodes to the end, preserving the order of - // the Pending/Waiting nodes. + // Move removable nodes to the end, preserving the order of the + // remaining nodes. // // LOOP INVARIANT: // self.nodes[0..index - dead_nodes] are the first remaining nodes @@ -649,7 +640,7 @@ impl ObligationForest { node_rewrites[index] = orig_nodes_len; dead_nodes += 1; } - NodeState::Success => unreachable!() + NodeState::Success => unreachable!(), } } @@ -662,11 +653,7 @@ impl ObligationForest { node_rewrites.truncate(0); self.node_rewrites.replace(node_rewrites); - if do_completed == DoCompleted::Yes { - Some(removed_done_obligations) - } else { - None - } + if do_completed == DoCompleted::Yes { Some(removed_done_obligations) } else { None } } fn apply_rewrites(&mut self, node_rewrites: &[usize]) { diff --git a/src/librustc_data_structures/obligation_forest/tests.rs b/src/librustc_data_structures/obligation_forest/tests.rs index 54b6f6d0ad..995c99bfec 100644 --- a/src/librustc_data_structures/obligation_forest/tests.rs +++ b/src/librustc_data_structures/obligation_forest/tests.rs @@ -70,6 +70,7 @@ fn push_pop() { "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), "B" => ProcessResult::Error("B is for broken"), "C" => ProcessResult::Changed(vec![]), + "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); @@ -94,6 +95,7 @@ fn push_pop() { "A.2" => ProcessResult::Unchanged, "A.3" => ProcessResult::Changed(vec!["A.3.i"]), "D" => ProcessResult::Changed(vec!["D.1", "D.2"]), + "A.3.i" | "D.1" | "D.2" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); @@ -113,6 +115,7 @@ fn push_pop() { "A.3.i" => ProcessResult::Changed(vec![]), "D.1" => ProcessResult::Changed(vec!["D.1.i"]), "D.2" => ProcessResult::Changed(vec!["D.2.i"]), + "D.1.i" | "D.2.i" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); @@ -161,35 +164,38 @@ fn success_in_grandchildren() { forest.process_obligations(&mut C(|obligation| { match *obligation { "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), + "A.1" => ProcessResult::Changed(vec![]), + "A.2" => ProcessResult::Changed(vec!["A.2.i", "A.2.ii"]), + "A.3" => ProcessResult::Changed(vec![]), + "A.2.i" | "A.2.ii" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); - assert!(ok.unwrap().is_empty()); + let mut ok = ok.unwrap(); + ok.sort(); + assert_eq!(ok, vec!["A.1", "A.3"]); assert!(err.is_empty()); let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C(|obligation| { match *obligation { - "A.1" => ProcessResult::Changed(vec![]), - "A.2" => ProcessResult::Changed(vec!["A.2.i", "A.2.ii"]), - "A.3" => ProcessResult::Changed(vec![]), + "A.2.i" => ProcessResult::Unchanged, + "A.2.ii" => ProcessResult::Changed(vec![]), _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); - let mut ok = ok.unwrap(); - ok.sort(); - assert_eq!(ok, vec!["A.1", "A.3"]); + assert_eq!(ok.unwrap(), vec!["A.2.ii"]); assert!(err.is_empty()); let Outcome { completed: ok, errors: err, .. } = forest.process_obligations(&mut C(|obligation| { match *obligation { "A.2.i" => ProcessResult::Changed(vec!["A.2.i.a"]), - "A.2.ii" => ProcessResult::Changed(vec![]), + "A.2.i.a" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_| {}), DoCompleted::Yes); - assert_eq!(ok.unwrap(), vec!["A.2.ii"]); + assert!(ok.unwrap().is_empty()); assert!(err.is_empty()); let Outcome { completed: ok, errors: err, .. } = @@ -222,6 +228,7 @@ fn to_errors_no_throw() { forest.process_obligations(&mut C(|obligation| { match *obligation { "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]), + "A.1" | "A.2" | "A.3" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); @@ -243,6 +250,7 @@ fn diamond() { forest.process_obligations(&mut C(|obligation| { match *obligation { "A" => ProcessResult::Changed(vec!["A.1", "A.2"]), + "A.1" | "A.2" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); @@ -254,6 +262,7 @@ fn diamond() { match *obligation { "A.1" => ProcessResult::Changed(vec!["D"]), "A.2" => ProcessResult::Changed(vec!["D"]), + "D" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); @@ -282,6 +291,7 @@ fn diamond() { forest.process_obligations(&mut C(|obligation| { match *obligation { "A'" => ProcessResult::Changed(vec!["A'.1", "A'.2"]), + "A'.1" | "A'.2" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); @@ -293,6 +303,7 @@ fn diamond() { match *obligation { "A'.1" => ProcessResult::Changed(vec!["D'", "A'"]), "A'.2" => ProcessResult::Changed(vec!["D'"]), + "D'" | "A'" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); @@ -370,6 +381,7 @@ fn orphan() { "B" => ProcessResult::Unchanged, "C1" => ProcessResult::Changed(vec![]), "C2" => ProcessResult::Changed(vec![]), + "D" | "E" => ProcessResult::Unchanged, _ => unreachable!(), } }, |_|{}), DoCompleted::Yes); diff --git a/src/librustc/util/profiling.rs b/src/librustc_data_structures/profiling.rs similarity index 88% rename from src/librustc/util/profiling.rs rename to src/librustc_data_structures/profiling.rs index 5a1b7f3aa4..f9bfe5a165 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -7,9 +7,7 @@ use std::sync::Arc; use std::thread::ThreadId; use std::u32; -use crate::ty::query::QueryName; - -use measureme::{StringId, TimestampKind}; +use measureme::{StringId}; /// MmapSerializatioSink is faster on macOS and Linux /// but FileSerializationSink is faster on Windows @@ -20,6 +18,10 @@ type SerializationSink = measureme::FileSerializationSink; type Profiler = measureme::Profiler; +pub trait QueryName: Sized + Copy { + fn discriminant(self) -> Discriminant; + fn as_str(self) -> &'static str; +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)] pub enum ProfileCategory { @@ -32,7 +34,7 @@ pub enum ProfileCategory { Other, } -bitflags! { +bitflags::bitflags! { struct EventFilter: u32 { const GENERIC_ACTIVITIES = 1 << 0; const QUERY_PROVIDERS = 1 << 1; @@ -61,8 +63,8 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("incr-cache-load", EventFilter::INCR_CACHE_LOADS), ]; -fn thread_id_to_u64(tid: ThreadId) -> u64 { - unsafe { mem::transmute::(tid) } +fn thread_id_to_u32(tid: ThreadId) -> u32 { + unsafe { mem::transmute::(tid) as u32 } } @@ -137,7 +139,7 @@ impl SelfProfilerRef { /// Start profiling a query provider. Profiling continues until the /// TimingGuard returned from this call is dropped. #[inline(always)] - pub fn query_provider(&self, query_name: QueryName) -> TimingGuard<'_> { + pub fn query_provider(&self, query_name: impl QueryName) -> TimingGuard<'_> { self.exec(EventFilter::QUERY_PROVIDERS, |profiler| { let event_id = SelfProfiler::get_query_name_string_id(query_name); TimingGuard::start(profiler, profiler.query_event_kind, event_id) @@ -146,12 +148,11 @@ impl SelfProfilerRef { /// Record a query in-memory cache hit. #[inline(always)] - pub fn query_cache_hit(&self, query_name: QueryName) { - self.non_guard_query_event( + pub fn query_cache_hit(&self, query_name: impl QueryName) { + self.instant_query_event( |profiler| profiler.query_cache_hit_event_kind, query_name, EventFilter::QUERY_CACHE_HITS, - TimestampKind::Instant, ); } @@ -159,7 +160,7 @@ impl SelfProfilerRef { /// Profiling continues until the TimingGuard returned from this call is /// dropped. #[inline(always)] - pub fn query_blocked(&self, query_name: QueryName) -> TimingGuard<'_> { + pub fn query_blocked(&self, query_name: impl QueryName) -> TimingGuard<'_> { self.exec(EventFilter::QUERY_BLOCKED, |profiler| { let event_id = SelfProfiler::get_query_name_string_id(query_name); TimingGuard::start(profiler, profiler.query_blocked_event_kind, event_id) @@ -170,7 +171,7 @@ impl SelfProfilerRef { /// incremental compilation on-disk cache. Profiling continues until the /// TimingGuard returned from this call is dropped. #[inline(always)] - pub fn incr_cache_loading(&self, query_name: QueryName) -> TimingGuard<'_> { + pub fn incr_cache_loading(&self, query_name: impl QueryName) -> TimingGuard<'_> { self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| { let event_id = SelfProfiler::get_query_name_string_id(query_name); TimingGuard::start( @@ -182,27 +183,31 @@ impl SelfProfilerRef { } #[inline(always)] - fn non_guard_query_event( + fn instant_query_event( &self, event_kind: fn(&SelfProfiler) -> StringId, - query_name: QueryName, + query_name: impl QueryName, event_filter: EventFilter, - timestamp_kind: TimestampKind ) { drop(self.exec(event_filter, |profiler| { let event_id = SelfProfiler::get_query_name_string_id(query_name); - let thread_id = thread_id_to_u64(std::thread::current().id()); + let thread_id = thread_id_to_u32(std::thread::current().id()); - profiler.profiler.record_event( + profiler.profiler.record_instant_event( event_kind(profiler), event_id, thread_id, - timestamp_kind, ); TimingGuard::none() })); } + + pub fn register_queries(&self, f: impl FnOnce(&SelfProfiler)) { + if let Some(profiler) = &self.profiler { + f(&profiler) + } + } } pub struct SelfProfiler { @@ -274,15 +279,15 @@ impl SelfProfiler { }) } - fn get_query_name_string_id(query_name: QueryName) -> StringId { + fn get_query_name_string_id(query_name: impl QueryName) -> StringId { let discriminant = unsafe { - mem::transmute::, u64>(mem::discriminant(&query_name)) + mem::transmute::, u64>(query_name.discriminant()) }; StringId::reserved(discriminant as u32) } - pub fn register_query_name(&self, query_name: QueryName) { + pub fn register_query_name(&self, query_name: impl QueryName) { let id = SelfProfiler::get_query_name_string_id(query_name); self.profiler.alloc_string_with_reserved_id(id, query_name.as_str()); } @@ -298,7 +303,7 @@ impl<'a> TimingGuard<'a> { event_kind: StringId, event_id: StringId, ) -> TimingGuard<'a> { - let thread_id = thread_id_to_u64(std::thread::current().id()); + let thread_id = thread_id_to_u32(std::thread::current().id()); let raw_profiler = &profiler.profiler; let timing_guard = raw_profiler.start_recording_interval_event(event_kind, event_id, diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index 2f972eeccd..a28a5e0f04 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -60,6 +60,7 @@ impl Sharded { } } + /// The shard is selected by hashing `val` with `FxHasher`. #[inline] pub fn get_shard_by_value(&self, val: &K) -> &Lock { if SHARDS == 1 { @@ -69,6 +70,11 @@ impl Sharded { } } + /// Get a shard with a pre-computed hash value. If `get_shard_by_value` is + /// ever used in combination with `get_shard_by_hash` on a single `Sharded` + /// instance, then `hash` must be computed with `FxHasher`. Otherwise, + /// `hash` can be computed with any hasher, so long as that hasher is used + /// consistently for each `Sharded` instance. #[inline] pub fn get_shard_by_hash(&self, hash: u64) -> &Lock { let hash_len = mem::size_of::(); diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 092208cfe1..70492d4992 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -149,7 +149,7 @@ impl Hasher for StableHasher { /// /// That second condition is usually not required for hash functions /// (e.g. `Hash`). In practice this means that `hash_stable` must feed any -/// information into the hasher that a `PartialEq` comparision takes into +/// information into the hasher that a `PartialEq` comparison takes into /// account. See [#49300](https://github.com/rust-lang/rust/issues/49300) /// for an example where violating this invariant has caused trouble in the /// past. @@ -429,6 +429,16 @@ impl HashStable for ::std::mem::Discriminant { } } +impl HashStable for ::std::ops::RangeInclusive + where T: HashStable +{ + #[inline] + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.start().hash_stable(ctx, hasher); + self.end().hash_stable(ctx, hasher); + } +} + impl HashStable for vec::IndexVec where T: HashStable, { diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index 371f0f6fa0..78cbc1240b 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -16,41 +16,29 @@ mod tests; #[derive(Clone)] pub struct TinyList { - head: Option> + head: Option>, } impl TinyList { #[inline] pub fn new() -> TinyList { - TinyList { - head: None - } + TinyList { head: None } } #[inline] pub fn new_single(data: T) -> TinyList { - TinyList { - head: Some(Element { - data, - next: None, - }) - } + TinyList { head: Some(Element { data, next: None }) } } #[inline] pub fn insert(&mut self, data: T) { - self.head = Some(Element { - data, - next: self.head.take().map(Box::new) - }); + self.head = Some(Element { data, next: self.head.take().map(Box::new) }); } #[inline] pub fn remove(&mut self, data: &T) -> bool { self.head = match self.head { - Some(ref mut head) if head.data == *data => { - head.next.take().map(|x| *x) - } + Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x), Some(ref mut head) => return head.remove_next(data), None => return false, }; @@ -88,12 +76,16 @@ struct Element { impl Element { fn remove_next(&mut self, data: &T) -> bool { - let new_next = match self.next { - Some(ref mut next) if next.data == *data => next.next.take(), - Some(ref mut next) => return next.remove_next(data), - None => return false, - }; - self.next = new_next; - true + let mut n = self; + loop { + match n.next { + Some(ref mut next) if next.data == *data => { + n.next = next.next.take(); + return true; + } + Some(ref mut next) => n = next, + None => return false, + } + } } } diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index a3926c1555..bbf6999b98 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -373,6 +373,14 @@ impl TransitiveRelation { } matrix } + + /// Lists all the base edges in the graph: the initial _non-transitive_ set of element + /// relations, which will be later used as the basis for the transitive closure computation. + pub fn base_edges(&self) -> impl Iterator { + self.edges + .iter() + .map(move |edge| (&self.elements[edge.source.0], &self.elements[edge.target.0])) + } } /// Pare down is used as a step in the LUB computation. It edits the diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index a9e4e6db1c..043cfc5897 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -19,13 +19,19 @@ rustc_target = { path = "../librustc_target" } rustc_lint = { path = "../librustc_lint" } rustc_data_structures = { path = "../librustc_data_structures" } errors = { path = "../librustc_errors", package = "rustc_errors" } +rustc_feature = { path = "../librustc_feature" } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } -rustc_plugin = { path = "../librustc_plugin/deprecated" } # To get this in the sysroot -rustc_plugin_impl = { path = "../librustc_plugin" } +rustc_parse = { path = "../librustc_parse" } +rustc_plugin_impl = { path = "../librustc_plugin_impl" } rustc_save_analysis = { path = "../librustc_save_analysis" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_error_codes = { path = "../librustc_error_codes" } rustc_interface = { path = "../librustc_interface" } rustc_serialize = { path = "../libserialize", package = "serialize" } +rustc_resolve = { path = "../librustc_resolve" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } + +[features] +llvm = ['rustc_interface/llvm'] diff --git a/src/librustc_driver/args.rs b/src/librustc_driver/args.rs index 0906d358ba..339a10f914 100644 --- a/src/librustc_driver/args.rs +++ b/src/librustc_driver/args.rs @@ -3,22 +3,12 @@ use std::fmt; use std::fs; use std::io; use std::str; -use std::sync::atomic::{AtomicBool, Ordering}; - -static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); - -pub fn used_unstable_argsfile() -> bool { - USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) -} pub fn arg_expand(arg: String) -> Result, Error> { if arg.starts_with("@") { let path = &arg[1..]; let file = match fs::read_to_string(path) { - Ok(file) => { - USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); - file - } + Ok(file) => file, Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { return Err(Error::Utf8Error(Some(path.to_string()))); } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6e8bc11162..3230e048a3 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -25,8 +25,6 @@ extern crate lazy_static; pub extern crate rustc_plugin_impl as plugin; -use pretty::{PpMode, UserIdentifiedItem}; - //use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; @@ -42,10 +40,11 @@ use rustc::ty::TyCtxt; use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported}; use rustc_metadata::locator; use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_interface::interface; -use rustc_interface::util::get_codegen_sysroot; +use errors::{PResult, registry::Registry}; +use rustc_interface::{interface, Queries}; +use rustc_interface::util::get_builtin_codegen_backend; use rustc_data_structures::sync::SeqCst; - +use rustc_feature::{find_gated_cfg, UnstableFeatures}; use rustc_serialize::json::ToJson; use std::borrow::Cow; @@ -62,11 +61,9 @@ use std::str; use std::time::Instant; use syntax::ast; -use syntax::source_map::FileLoader; -use syntax::feature_gate::{GatedCfg, UnstableFeatures}; -use syntax::parse::{self, PResult}; -use syntax::symbol::sym; -use syntax_pos::{DUMMY_SP, FileName}; +use syntax_pos::source_map::FileLoader; +use syntax_pos::symbol::sym; +use syntax_pos::FileName; pub mod pretty; mod args; @@ -86,13 +83,6 @@ const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"]; -pub fn source_name(input: &Input) -> FileName { - match *input { - Input::File(ref ifile) => ifile.clone().into(), - Input::Str { ref name, .. } => name.clone(), - } -} - pub fn abort_on_err(result: Result, sess: &Session) -> T { match result { Err(..) => { @@ -108,17 +98,29 @@ pub trait Callbacks { fn config(&mut self, _config: &mut interface::Config) {} /// Called after parsing. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) - fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation { + fn after_parsing<'tcx>( + &mut self, + _compiler: &interface::Compiler, + _queries: &'tcx Queries<'tcx>, + ) -> Compilation { Compilation::Continue } /// Called after expansion. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) - fn after_expansion(&mut self, _compiler: &interface::Compiler) -> Compilation { + fn after_expansion<'tcx>( + &mut self, + _compiler: &interface::Compiler, + _queries: &'tcx Queries<'tcx>, + ) -> Compilation { Compilation::Continue } /// Called after analysis. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) - fn after_analysis(&mut self, _compiler: &interface::Compiler) -> Compilation { + fn after_analysis<'tcx>( + &mut self, + _compiler: &interface::Compiler, + _queries: &'tcx Queries<'tcx>, + ) -> Compilation { Compilation::Continue } } @@ -142,6 +144,10 @@ impl Callbacks for TimePassesCallbacks { } } +pub fn diagnostics_registry() -> Registry { + Registry::new(&rustc_error_codes::DIAGNOSTICS) +} + // Parse args and run the compiler. This is the primary entry point for rustc. // See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. @@ -183,13 +189,15 @@ pub fn run_compiler( crate_name: None, lint_caps: Default::default(), register_lints: None, + override_queries: None, + registry: diagnostics_registry(), }; callbacks.config(&mut config); config }; if let Some(ref code) = matches.opt_str("explain") { - handle_explain(code, sopts.error_format); + handle_explain(diagnostics_registry(), code, sopts.error_format); return Ok(()); } @@ -261,6 +269,8 @@ pub fn run_compiler( crate_name: None, lint_caps: Default::default(), register_lints: None, + override_queries: None, + registry: diagnostics_registry(), }; callbacks.config(&mut config); @@ -284,126 +294,128 @@ pub fn run_compiler( return sess.compile_status(); } - let pretty_info = parse_pretty(sess, &matches); - - compiler.parse()?; - - if let Some((ppm, opt_uii)) = pretty_info { - if ppm.needs_ast_map(&opt_uii) { - pretty::visit_crate(sess, &mut compiler.parse()?.peek_mut(), ppm); - compiler.global_ctxt()?.peek_mut().enter(|tcx| { - let expanded_crate = compiler.expansion()?.take().0; - pretty::print_after_hir_lowering( - tcx, - compiler.input(), - &expanded_crate, - ppm, - opt_uii.clone(), + let linker = compiler.enter(|queries| { + let early_exit = || sess.compile_status().map(|_| None); + queries.parse()?; + + if let Some(ppm) = &sess.opts.pretty { + if ppm.needs_ast_map() { + queries.global_ctxt()?.peek_mut().enter(|tcx| { + let expanded_crate = queries.expansion()?.take().0; + pretty::print_after_hir_lowering( + tcx, + compiler.input(), + &expanded_crate, + *ppm, + compiler.output_file().as_ref().map(|p| &**p), + ); + Ok(()) + })?; + } else { + let krate = queries.parse()?.take(); + pretty::print_after_parsing( + sess, + &compiler.input(), + &krate, + *ppm, compiler.output_file().as_ref().map(|p| &**p), ); - Ok(()) - })?; - } else { - let mut krate = compiler.parse()?.take(); - pretty::visit_crate(sess, &mut krate, ppm); - pretty::print_after_parsing( - sess, - &compiler.input(), - &krate, - ppm, - compiler.output_file().as_ref().map(|p| &**p), - ); + } + return early_exit(); } - return sess.compile_status(); - } - if callbacks.after_parsing(compiler) == Compilation::Stop { - return sess.compile_status(); - } + if callbacks.after_parsing(compiler, queries) == Compilation::Stop { + return early_exit(); + } - if sess.opts.debugging_opts.parse_only || - sess.opts.debugging_opts.show_span.is_some() || - sess.opts.debugging_opts.ast_json_noexpand { - return sess.compile_status(); - } + if sess.opts.debugging_opts.parse_only || + sess.opts.debugging_opts.show_span.is_some() || + sess.opts.debugging_opts.ast_json_noexpand { + return early_exit(); + } - { - let (_, _, lint_store) = &*compiler.register_plugins()?.peek(); + { + let (_, lint_store) = &*queries.register_plugins()?.peek(); - // Lint plugins are registered; now we can process command line flags. - if sess.opts.describe_lints { - describe_lints(&sess, &lint_store, true); - return sess.compile_status(); + // Lint plugins are registered; now we can process command line flags. + if sess.opts.describe_lints { + describe_lints(&sess, &lint_store, true); + return early_exit(); + } } - } - compiler.expansion()?; - if callbacks.after_expansion(compiler) == Compilation::Stop { - return sess.compile_status(); - } + queries.expansion()?; + if callbacks.after_expansion(compiler, queries) == Compilation::Stop { + return early_exit(); + } - compiler.prepare_outputs()?; + queries.prepare_outputs()?; - if sess.opts.output_types.contains_key(&OutputType::DepInfo) - && sess.opts.output_types.len() == 1 - { - return sess.compile_status(); - } + if sess.opts.output_types.contains_key(&OutputType::DepInfo) + && sess.opts.output_types.len() == 1 + { + return early_exit(); + } - compiler.global_ctxt()?; + queries.global_ctxt()?; - if sess.opts.debugging_opts.no_analysis || - sess.opts.debugging_opts.ast_json { - return sess.compile_status(); - } + if sess.opts.debugging_opts.no_analysis || + sess.opts.debugging_opts.ast_json { + return early_exit(); + } - if sess.opts.debugging_opts.save_analysis { - let expanded_crate = &compiler.expansion()?.peek().0; - let crate_name = compiler.crate_name()?.peek().clone(); - compiler.global_ctxt()?.peek_mut().enter(|tcx| { - let result = tcx.analysis(LOCAL_CRATE); - - time(sess, "save analysis", || { - save::process_crate( - tcx, - &expanded_crate, - &crate_name, - &compiler.input(), - None, - DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name) - ) - }); - - result - // AST will be dropped *after* the `after_analysis` callback - // (needed by the RLS) - })?; - } else { - // Drop AST after creating GlobalCtxt to free memory - mem::drop(compiler.expansion()?.take()); - } + if sess.opts.debugging_opts.save_analysis { + let expanded_crate = &queries.expansion()?.peek().0; + let crate_name = queries.crate_name()?.peek().clone(); + queries.global_ctxt()?.peek_mut().enter(|tcx| { + let result = tcx.analysis(LOCAL_CRATE); + + time(sess, "save analysis", || { + save::process_crate( + tcx, + &expanded_crate, + &crate_name, + &compiler.input(), + None, + DumpHandler::new( + compiler.output_dir().as_ref().map(|p| &**p), &crate_name + ) + ) + }); - compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; + result + // AST will be dropped *after* the `after_analysis` callback + // (needed by the RLS) + })?; + } else { + // Drop AST after creating GlobalCtxt to free memory + mem::drop(queries.expansion()?.take()); + } - if callbacks.after_analysis(compiler) == Compilation::Stop { - return sess.compile_status(); - } + queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?; - if sess.opts.debugging_opts.save_analysis { - mem::drop(compiler.expansion()?.take()); - } + if callbacks.after_analysis(compiler, queries) == Compilation::Stop { + return early_exit(); + } + + if sess.opts.debugging_opts.save_analysis { + mem::drop(queries.expansion()?.take()); + } + + queries.ongoing_codegen()?; - compiler.ongoing_codegen()?; + if sess.opts.debugging_opts.print_type_sizes { + sess.code_stats.print_type_sizes(); + } - // Drop GlobalCtxt after starting codegen to free memory - mem::drop(compiler.global_ctxt()?.take()); + let linker = queries.linker()?; + Ok(Some(linker)) + })?; - if sess.opts.debugging_opts.print_type_sizes { - sess.code_stats.borrow().print_type_sizes(); + if let Some(linker) = linker { + linker.link()? } - compiler.link()?; - if sess.opts.debugging_opts.perf_stats { sess.print_perf_stats(); } @@ -469,28 +481,6 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option, Option } } -fn parse_pretty(sess: &Session, - matches: &getopts::Matches) - -> Option<(PpMode, Option)> { - let pretty = if sess.opts.debugging_opts.unstable_options { - matches.opt_default("pretty", "normal").map(|a| { - // stable pretty-print variants only - pretty::parse_pretty(sess, &a, false) - }) - } else { - None - }; - - if pretty.is_none() { - sess.opts.debugging_opts.unpretty.as_ref().map(|a| { - // extended with unstable pretty-print variants - pretty::parse_pretty(sess, &a, true) - }) - } else { - pretty - } -} - // Whether to stop or continue compilation. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Compilation { @@ -536,27 +526,25 @@ fn stdout_isatty() -> bool { } } -fn handle_explain(code: &str, - output: ErrorOutputType) { - let descriptions = rustc_interface::util::diagnostics_registry(); +fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let normalised = if code.starts_with("E") { code.to_string() } else { format!("E{0:0>4}", code) }; - match descriptions.find_description(&normalised) { + match registry.find_description(&normalised) { Some(ref description) => { let mut is_in_code_block = false; let mut text = String::new(); // Slice off the leading newline and print. - for line in description[1..].lines() { + for line in description.lines() { let indent_level = line.find(|c: char| !c.is_whitespace()) .unwrap_or_else(|| line.len()); let dedented_line = &line[indent_level..]; if dedented_line.starts_with("```") { is_in_code_block = !is_in_code_block; - text.push_str(&line[..(indent_level+3)]); + text.push_str(&line[..(indent_level + 3)]); } else if is_in_code_block && dedented_line.starts_with("# ") { continue; } else { @@ -707,12 +695,6 @@ impl RustcDefaultCalls { .is_nightly_build(); let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| { - let gated_cfg = GatedCfg::gate(&ast::MetaItem { - path: ast::Path::from_ident(ast::Ident::with_dummy_span(name)), - kind: ast::MetaItemKind::Word, - span: DUMMY_SP, - }); - // Note that crt-static is a specially recognized cfg // directive that's printed out here as part of // rust-lang/rust#37406, but in general the @@ -723,10 +705,11 @@ impl RustcDefaultCalls { // through to build scripts. let value = value.as_ref().map(|s| s.as_str()); let value = value.as_ref().map(|s| s.as_ref()); - if name != sym::target_feature || value != Some("crt-static") { - if !allow_unstable_cfg && gated_cfg.is_some() { - return None - } + if (name != sym::target_feature || value != Some("crt-static")) + && !allow_unstable_cfg + && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some() + { + return None; } if let Some(value) = value { @@ -782,7 +765,7 @@ pub fn version(binary: &str, matches: &getopts::Matches) { println!("commit-date: {}", unw(commit_date_str())); println!("host: {}", config::host_triple()); println!("release: {}", unw(release_str())); - get_codegen_sysroot("llvm")().print_version(); + get_builtin_codegen_backend("llvm")().print_version(); } } @@ -845,7 +828,7 @@ Available lint options: fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> { // The sort doesn't case-fold but it's doubtful we care. - lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name)); + lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name)); lints } @@ -1043,12 +1026,6 @@ pub fn handle_options(args: &[String]) -> Option { // (unstable option being used on stable) nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); - // Late check to see if @file was used without unstable options enabled - if crate::args::used_unstable_argsfile() && !nightly_options::is_unstable_enabled(&matches) { - early_error(ErrorOutputType::default(), - "@path is unstable - use -Z unstable-options to enable its use"); - } - if matches.opt_present("h") || matches.opt_present("help") { // Only show unstable options in --help if we accept unstable options. usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches)); @@ -1082,7 +1059,7 @@ pub fn handle_options(args: &[String]) -> Option { } if cg_flags.iter().any(|x| *x == "passes=list") { - get_codegen_sysroot("llvm")().print_passes(); + get_builtin_codegen_backend("llvm")().print_passes(); return None; } @@ -1095,14 +1072,16 @@ pub fn handle_options(args: &[String]) -> Option { } fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec> { - match *input { - Input::File(ref ifile) => { - parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess) + match input { + Input::File(ifile) => { + rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess) } - Input::Str { ref name, ref input } => { - parse::parse_crate_attrs_from_source_str(name.clone(), - input.clone(), - &sess.parse_sess) + Input::Str { name, input } => { + rustc_parse::parse_crate_attrs_from_source_str( + name.clone(), + input.clone(), + &sess.parse_sess, + ) } } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 0de5b700b4..11603f6d9c 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -5,119 +5,24 @@ use rustc::hir::map as hir_map; use rustc::hir::print as pprust_hir; use rustc::hir::def_id::LOCAL_CRATE; use rustc::session::Session; -use rustc::session::config::Input; +use rustc::session::config::{PpMode, PpSourceMode, Input}; use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; -use rustc_interface::util::ReplaceBodyWithLoop; use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; use syntax::ast; -use syntax::mut_visit::MutVisitor; use syntax::print::{pprust}; use syntax_pos::FileName; use std::cell::Cell; use std::fs::File; use std::io::Write; -use std::option; use std::path::Path; -use std::str::FromStr; -pub use self::UserIdentifiedItem::*; pub use self::PpSourceMode::*; pub use self::PpMode::*; -use self::NodesMatchingUII::*; use crate::abort_on_err; -use crate::source_name; - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum PpSourceMode { - PpmNormal, - PpmEveryBodyLoops, - PpmExpanded, - PpmIdentified, - PpmExpandedIdentified, - PpmExpandedHygiene, - PpmTyped, -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum PpMode { - PpmSource(PpSourceMode), - PpmHir(PpSourceMode), - PpmHirTree(PpSourceMode), - PpmMir, - PpmMirCFG, -} - -impl PpMode { - pub fn needs_ast_map(&self, opt_uii: &Option) -> bool { - match *self { - PpmSource(PpmNormal) | - PpmSource(PpmEveryBodyLoops) | - PpmSource(PpmIdentified) => opt_uii.is_some(), - - PpmSource(PpmExpanded) | - PpmSource(PpmExpandedIdentified) | - PpmSource(PpmExpandedHygiene) | - PpmHir(_) | - PpmHirTree(_) | - PpmMir | - PpmMirCFG => true, - PpmSource(PpmTyped) => panic!("invalid state"), - } - } - - pub fn needs_analysis(&self) -> bool { - match *self { - PpmMir | PpmMirCFG => true, - _ => false, - } - } -} - -pub fn parse_pretty(sess: &Session, - name: &str, - extended: bool) - -> (PpMode, Option) { - let mut split = name.splitn(2, '='); - let first = split.next().unwrap(); - let opt_second = split.next(); - let first = match (first, extended) { - ("normal", _) => PpmSource(PpmNormal), - ("identified", _) => PpmSource(PpmIdentified), - ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), - ("expanded", _) => PpmSource(PpmExpanded), - ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), - ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), - ("hir", true) => PpmHir(PpmNormal), - ("hir,identified", true) => PpmHir(PpmIdentified), - ("hir,typed", true) => PpmHir(PpmTyped), - ("hir-tree", true) => PpmHirTree(PpmNormal), - ("mir", true) => PpmMir, - ("mir-cfg", true) => PpmMirCFG, - _ => { - if extended { - sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \ - `expanded`, `identified`, `expanded,identified`, \ - `expanded,hygiene`, `everybody_loops`, \ - `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \ - `mir` or `mir-cfg`; got {}", - name)); - } else { - sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \ - `identified`, or `expanded,identified`; got {}", - name)); - } - } - }; - let opt_second = opt_second.and_then(|s| s.parse::().ok()); - (first, opt_second) -} - - - // This slightly awkward construction is to allow for each PpMode to // choose whether it needs to do analyses (which can consume the // Session) and then pass through the session (now attached to the @@ -131,76 +36,74 @@ pub fn parse_pretty(sess: &Session, // (The `use_once_payload` is working around the current lack of once // functions in the compiler.) -impl PpSourceMode { - /// Constructs a `PrinterSupport` object and passes it to `f`. - fn call_with_pp_support<'tcx, A, F>( - &self, - sess: &'tcx Session, - tcx: Option>, - f: F, - ) -> A - where - F: FnOnce(&dyn PrinterSupport) -> A, - { - match *self { - PpmNormal | PpmEveryBodyLoops | PpmExpanded => { - let annotation = NoAnn { - sess, - tcx, - }; - f(&annotation) - } +/// Constructs a `PrinterSupport` object and passes it to `f`. +fn call_with_pp_support<'tcx, A, F>( + ppmode: &PpSourceMode, + sess: &'tcx Session, + tcx: Option>, + f: F, +) -> A +where + F: FnOnce(&dyn PrinterSupport) -> A, +{ + match *ppmode { + PpmNormal | PpmEveryBodyLoops | PpmExpanded => { + let annotation = NoAnn { + sess, + tcx, + }; + f(&annotation) + } - PpmIdentified | PpmExpandedIdentified => { - let annotation = IdentifiedAnnotation { - sess, - tcx, - }; - f(&annotation) - } - PpmExpandedHygiene => { - let annotation = HygieneAnnotation { - sess, - }; - f(&annotation) - } - _ => panic!("Should use call_with_pp_support_hir"), + PpmIdentified | PpmExpandedIdentified => { + let annotation = IdentifiedAnnotation { + sess, + tcx, + }; + f(&annotation) + } + PpmExpandedHygiene => { + let annotation = HygieneAnnotation { + sess, + }; + f(&annotation) + } + _ => panic!("Should use call_with_pp_support_hir"), + } +} +fn call_with_pp_support_hir(ppmode: &PpSourceMode, tcx: TyCtxt<'_>, f: F) -> A +where + F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A, +{ + match *ppmode { + PpmNormal => { + let annotation = NoAnn { + sess: tcx.sess, + tcx: Some(tcx), + }; + f(&annotation, tcx.hir().forest.krate()) } - } - fn call_with_pp_support_hir(&self, tcx: TyCtxt<'_>, f: F) -> A - where - F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A, - { - match *self { - PpmNormal => { - let annotation = NoAnn { - sess: tcx.sess, - tcx: Some(tcx), - }; - f(&annotation, tcx.hir().forest.krate()) - } - PpmIdentified => { - let annotation = IdentifiedAnnotation { - sess: tcx.sess, - tcx: Some(tcx), - }; + PpmIdentified => { + let annotation = IdentifiedAnnotation { + sess: tcx.sess, + tcx: Some(tcx), + }; + f(&annotation, tcx.hir().forest.krate()) + } + PpmTyped => { + abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); + + let empty_tables = ty::TypeckTables::empty(None); + let annotation = TypedAnnotation { + tcx, + tables: Cell::new(&empty_tables) + }; + tcx.dep_graph.with_ignore(|| { f(&annotation, tcx.hir().forest.krate()) - } - PpmTyped => { - abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); - - let empty_tables = ty::TypeckTables::empty(None); - let annotation = TypedAnnotation { - tcx, - tables: Cell::new(&empty_tables) - }; - tcx.dep_graph.with_ignore(|| { - f(&annotation, tcx.hir().forest.krate()) - }) - } - _ => panic!("Should use call_with_pp_support"), + }) } + _ => panic!("Should use call_with_pp_support"), } } @@ -482,104 +385,8 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { } } -#[derive(Clone, Debug)] -pub enum UserIdentifiedItem { - ItemViaNode(ast::NodeId), - ItemViaPath(Vec), -} - -impl FromStr for UserIdentifiedItem { - type Err = (); - fn from_str(s: &str) -> Result { - Ok(s.parse() - .map(ast::NodeId::from_u32) - .map(ItemViaNode) - .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) - } -} - -enum NodesMatchingUII<'a> { - NodesMatchingDirect(option::IntoIter), - NodesMatchingSuffix(Box + 'a>), -} - -impl<'a> Iterator for NodesMatchingUII<'a> { - type Item = ast::NodeId; - - fn next(&mut self) -> Option { - match self { - &mut NodesMatchingDirect(ref mut iter) => iter.next(), - &mut NodesMatchingSuffix(ref mut iter) => iter.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match self { - &NodesMatchingDirect(ref iter) => iter.size_hint(), - &NodesMatchingSuffix(ref iter) => iter.size_hint(), - } - } -} - -impl UserIdentifiedItem { - fn reconstructed_input(&self) -> String { - match *self { - ItemViaNode(node_id) => node_id.to_string(), - ItemViaPath(ref parts) => parts.join("::"), - } - } - - fn all_matching_node_ids<'a, 'hir>(&'a self, - map: &'a hir_map::Map<'hir>) - -> NodesMatchingUII<'a> { - match *self { - ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), - ItemViaPath(ref parts) => { - NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) - } - } - } - - fn to_one_node_id(self, - user_option: &str, - sess: &Session, - map: &hir_map::Map<'_>) - -> ast::NodeId { - let fail_because = |is_wrong_because| -> ast::NodeId { - let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ - {}, which {}", - user_option, - self.reconstructed_input(), - is_wrong_because); - sess.fatal(&message) - }; - - let mut saw_node = ast::DUMMY_NODE_ID; - let mut seen = 0; - for node in self.all_matching_node_ids(map) { - saw_node = node; - seen += 1; - if seen > 1 { - fail_because("does not resolve uniquely"); - } - } - if seen == 0 { - fail_because("does not resolve to any item"); - } - - assert!(seen == 1); - return saw_node; - } -} - -pub fn visit_crate(sess: &Session, krate: &mut ast::Crate, ppm: PpMode) { - if let PpmSource(PpmEveryBodyLoops) = ppm { - ReplaceBodyWithLoop::new(sess).visit_crate(krate); - } -} - fn get_source(input: &Input, sess: &Session) -> (String, FileName) { - let src_name = source_name(input); + let src_name = input.source_name(); let src = String::clone(&sess.source_map() .get_source_file(&src_name) .unwrap() @@ -613,7 +420,7 @@ pub fn print_after_parsing(sess: &Session, if let PpmSource(s) = ppm { // Silently ignores an identified node. let out = &mut out; - s.call_with_pp_support(sess, None, move |annotation| { + call_with_pp_support(&s, sess, None, move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust::print_crate(sess.source_map(), @@ -636,14 +443,12 @@ pub fn print_after_hir_lowering<'tcx>( input: &Input, krate: &ast::Crate, ppm: PpMode, - opt_uii: Option, ofile: Option<&Path>, ) { if ppm.needs_analysis() { abort_on_err(print_with_analysis( tcx, ppm, - opt_uii, ofile ), tcx.sess); return; @@ -653,12 +458,12 @@ pub fn print_after_hir_lowering<'tcx>( let mut out = String::new(); - match (ppm, opt_uii) { - (PpmSource(s), _) => { + match ppm { + PpmSource(s) => { // Silently ignores an identified node. let out = &mut out; let src = src.clone(); - s.call_with_pp_support(tcx.sess, Some(tcx), move |annotation| { + call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust::print_crate(sess.source_map(), @@ -671,10 +476,10 @@ pub fn print_after_hir_lowering<'tcx>( }) } - (PpmHir(s), None) => { + PpmHir(s) => { let out = &mut out; let src = src.clone(); - s.call_with_pp_support_hir(tcx, move |annotation, krate| { + call_with_pp_support_hir(&s, tcx, move |annotation, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust_hir::print_crate(sess.source_map(), @@ -686,52 +491,14 @@ pub fn print_after_hir_lowering<'tcx>( }) } - (PpmHirTree(s), None) => { + PpmHirTree(s) => { let out = &mut out; - s.call_with_pp_support_hir(tcx, move |_annotation, krate| { + call_with_pp_support_hir(&s, tcx, move |_annotation, krate| { debug!("pretty printing source code {:?}", s); *out = format!("{:#?}", krate); }); } - (PpmHir(s), Some(uii)) => { - let out = &mut out; - let src = src.clone(); - s.call_with_pp_support_hir(tcx, move |annotation, _| { - debug!("pretty printing source code {:?}", s); - let sess = annotation.sess(); - let hir_map = annotation.hir_map().expect("-Z unpretty missing HIR map"); - let mut pp_state = pprust_hir::State::new_from_input(sess.source_map(), - &sess.parse_sess, - src_name, - src, - annotation.pp_ann()); - for node_id in uii.all_matching_node_ids(hir_map) { - let hir_id = tcx.hir().node_to_hir_id(node_id); - let node = hir_map.get(hir_id); - pp_state.print_node(node); - pp_state.s.space(); - let path = annotation.node_path(hir_id) - .expect("-Z unpretty missing node paths"); - pp_state.synth_comment(path); - pp_state.s.hardbreak(); - } - *out = pp_state.s.eof(); - }) - } - - (PpmHirTree(s), Some(uii)) => { - let out = &mut out; - s.call_with_pp_support_hir(tcx, move |_annotation, _krate| { - debug!("pretty printing source code {:?}", s); - for node_id in uii.all_matching_node_ids(tcx.hir()) { - let hir_id = tcx.hir().node_to_hir_id(node_id); - let node = tcx.hir().get(hir_id); - out.push_str(&format!("{:#?}", node)); - } - }) - } - _ => unreachable!(), } @@ -745,27 +512,17 @@ pub fn print_after_hir_lowering<'tcx>( fn print_with_analysis( tcx: TyCtxt<'_>, ppm: PpMode, - uii: Option, ofile: Option<&Path>, ) -> Result<(), ErrorReported> { - let nodeid = if let Some(uii) = uii { - debug!("pretty printing for {:?}", uii); - Some(uii.to_one_node_id("-Z unpretty", tcx.sess, tcx.hir())) - } else { - debug!("pretty printing for whole crate"); - None - }; - let mut out = Vec::new(); tcx.analysis(LOCAL_CRATE)?; match ppm { PpmMir | PpmMirCFG => { - let def_id = nodeid.map(|nid| tcx.hir().local_def_id_from_node_id(nid)); match ppm { - PpmMir => write_mir_pretty(tcx, def_id, &mut out), - PpmMirCFG => write_mir_graphviz(tcx, def_id, &mut out), + PpmMir => write_mir_pretty(tcx, None, &mut out), + PpmMirCFG => write_mir_graphviz(tcx, None, &mut out), _ => unreachable!(), } } diff --git a/src/librustc_error_codes/Cargo.toml b/src/librustc_error_codes/Cargo.toml new file mode 100644 index 0000000000..5def867ff1 --- /dev/null +++ b/src/librustc_error_codes/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_error_codes" +version = "0.0.0" +edition = "2018" + +[lib] +name = "rustc_error_codes" +path = "lib.rs" diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs new file mode 100644 index 0000000000..9c1bec39b2 --- /dev/null +++ b/src/librustc_error_codes/error_codes.rs @@ -0,0 +1,612 @@ +// Error messages for EXXXX errors. Each message should start and end with a +// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and +// use `gq` to wrap paragraphs. Use `:set tw=0` to disable. +// +// /!\ IMPORTANT /!\ +// +// Error messages' format must follow the RFC 1567 available here: +// https://github.com/rust-lang/rfcs/pull/1567 + +register_diagnostics! { +E0001: include_str!("./error_codes/E0001.md"), +E0002: include_str!("./error_codes/E0002.md"), +E0004: include_str!("./error_codes/E0004.md"), +E0005: include_str!("./error_codes/E0005.md"), +E0007: include_str!("./error_codes/E0007.md"), +E0009: include_str!("./error_codes/E0009.md"), +E0010: include_str!("./error_codes/E0010.md"), +E0013: include_str!("./error_codes/E0013.md"), +E0014: include_str!("./error_codes/E0014.md"), +E0015: include_str!("./error_codes/E0015.md"), +E0019: include_str!("./error_codes/E0019.md"), +E0023: include_str!("./error_codes/E0023.md"), +E0025: include_str!("./error_codes/E0025.md"), +E0026: include_str!("./error_codes/E0026.md"), +E0027: include_str!("./error_codes/E0027.md"), +E0029: include_str!("./error_codes/E0029.md"), +E0030: include_str!("./error_codes/E0030.md"), +E0033: include_str!("./error_codes/E0033.md"), +E0034: include_str!("./error_codes/E0034.md"), +E0038: include_str!("./error_codes/E0038.md"), +E0040: include_str!("./error_codes/E0040.md"), +E0044: include_str!("./error_codes/E0044.md"), +E0045: include_str!("./error_codes/E0045.md"), +E0046: include_str!("./error_codes/E0046.md"), +E0049: include_str!("./error_codes/E0049.md"), +E0050: include_str!("./error_codes/E0050.md"), +E0053: include_str!("./error_codes/E0053.md"), +E0054: include_str!("./error_codes/E0054.md"), +E0055: include_str!("./error_codes/E0055.md"), +E0057: include_str!("./error_codes/E0057.md"), +E0059: include_str!("./error_codes/E0059.md"), +E0060: include_str!("./error_codes/E0060.md"), +E0061: include_str!("./error_codes/E0061.md"), +E0062: include_str!("./error_codes/E0062.md"), +E0063: include_str!("./error_codes/E0063.md"), +E0067: include_str!("./error_codes/E0067.md"), +E0069: include_str!("./error_codes/E0069.md"), +E0070: include_str!("./error_codes/E0070.md"), +E0071: include_str!("./error_codes/E0071.md"), +E0072: include_str!("./error_codes/E0072.md"), +E0073: include_str!("./error_codes/E0073.md"), +E0074: include_str!("./error_codes/E0074.md"), +E0075: include_str!("./error_codes/E0075.md"), +E0076: include_str!("./error_codes/E0076.md"), +E0077: include_str!("./error_codes/E0077.md"), +E0080: include_str!("./error_codes/E0080.md"), +E0081: include_str!("./error_codes/E0081.md"), +E0084: include_str!("./error_codes/E0084.md"), +E0087: include_str!("./error_codes/E0087.md"), +E0088: include_str!("./error_codes/E0088.md"), +E0089: include_str!("./error_codes/E0089.md"), +E0090: include_str!("./error_codes/E0090.md"), +E0091: include_str!("./error_codes/E0091.md"), +E0092: include_str!("./error_codes/E0092.md"), +E0093: include_str!("./error_codes/E0093.md"), +E0094: include_str!("./error_codes/E0094.md"), +E0106: include_str!("./error_codes/E0106.md"), +E0107: include_str!("./error_codes/E0107.md"), +E0109: include_str!("./error_codes/E0109.md"), +E0110: include_str!("./error_codes/E0110.md"), +E0116: include_str!("./error_codes/E0116.md"), +E0117: include_str!("./error_codes/E0117.md"), +E0118: include_str!("./error_codes/E0118.md"), +E0119: include_str!("./error_codes/E0119.md"), +E0120: include_str!("./error_codes/E0120.md"), +E0121: include_str!("./error_codes/E0121.md"), +E0124: include_str!("./error_codes/E0124.md"), +E0128: include_str!("./error_codes/E0128.md"), +E0130: include_str!("./error_codes/E0130.md"), +E0131: include_str!("./error_codes/E0131.md"), +E0132: include_str!("./error_codes/E0132.md"), +E0133: include_str!("./error_codes/E0133.md"), +E0136: include_str!("./error_codes/E0136.md"), +E0137: include_str!("./error_codes/E0137.md"), +E0138: include_str!("./error_codes/E0138.md"), +E0139: include_str!("./error_codes/E0139.md"), +E0152: include_str!("./error_codes/E0152.md"), +E0154: include_str!("./error_codes/E0154.md"), +E0158: include_str!("./error_codes/E0158.md"), +E0161: include_str!("./error_codes/E0161.md"), +E0162: include_str!("./error_codes/E0162.md"), +E0164: include_str!("./error_codes/E0164.md"), +E0165: include_str!("./error_codes/E0165.md"), +E0170: include_str!("./error_codes/E0170.md"), +E0178: include_str!("./error_codes/E0178.md"), +E0184: include_str!("./error_codes/E0184.md"), +E0185: include_str!("./error_codes/E0185.md"), +E0186: include_str!("./error_codes/E0186.md"), +E0191: include_str!("./error_codes/E0191.md"), +E0192: include_str!("./error_codes/E0192.md"), +E0193: include_str!("./error_codes/E0193.md"), +E0195: include_str!("./error_codes/E0195.md"), +E0197: include_str!("./error_codes/E0197.md"), +E0198: include_str!("./error_codes/E0198.md"), +E0199: include_str!("./error_codes/E0199.md"), +E0200: include_str!("./error_codes/E0200.md"), +E0201: include_str!("./error_codes/E0201.md"), +E0202: include_str!("./error_codes/E0202.md"), +E0203: include_str!("./error_codes/E0203.md"), +E0204: include_str!("./error_codes/E0204.md"), +E0205: include_str!("./error_codes/E0205.md"), +E0206: include_str!("./error_codes/E0206.md"), +E0207: include_str!("./error_codes/E0207.md"), +E0210: include_str!("./error_codes/E0210.md"), +E0211: include_str!("./error_codes/E0211.md"), +E0214: include_str!("./error_codes/E0214.md"), +E0220: include_str!("./error_codes/E0220.md"), +E0221: include_str!("./error_codes/E0221.md"), +E0223: include_str!("./error_codes/E0223.md"), +E0225: include_str!("./error_codes/E0225.md"), +E0229: include_str!("./error_codes/E0229.md"), +E0230: include_str!("./error_codes/E0230.md"), +E0231: include_str!("./error_codes/E0231.md"), +E0232: include_str!("./error_codes/E0232.md"), +E0243: include_str!("./error_codes/E0243.md"), +E0244: include_str!("./error_codes/E0244.md"), +E0251: include_str!("./error_codes/E0251.md"), +E0252: include_str!("./error_codes/E0252.md"), +E0253: include_str!("./error_codes/E0253.md"), +E0254: include_str!("./error_codes/E0254.md"), +E0255: include_str!("./error_codes/E0255.md"), +E0256: include_str!("./error_codes/E0256.md"), +E0259: include_str!("./error_codes/E0259.md"), +E0260: include_str!("./error_codes/E0260.md"), +E0261: include_str!("./error_codes/E0261.md"), +E0262: include_str!("./error_codes/E0262.md"), +E0263: include_str!("./error_codes/E0263.md"), +E0264: include_str!("./error_codes/E0264.md"), +E0267: include_str!("./error_codes/E0267.md"), +E0268: include_str!("./error_codes/E0268.md"), +E0271: include_str!("./error_codes/E0271.md"), +E0275: include_str!("./error_codes/E0275.md"), +E0276: include_str!("./error_codes/E0276.md"), +E0277: include_str!("./error_codes/E0277.md"), +E0281: include_str!("./error_codes/E0281.md"), +E0282: include_str!("./error_codes/E0282.md"), +E0283: include_str!("./error_codes/E0283.md"), +E0284: include_str!("./error_codes/E0284.md"), +E0297: include_str!("./error_codes/E0297.md"), +E0301: include_str!("./error_codes/E0301.md"), +E0302: include_str!("./error_codes/E0302.md"), +E0303: include_str!("./error_codes/E0303.md"), +E0307: include_str!("./error_codes/E0307.md"), +E0308: include_str!("./error_codes/E0308.md"), +E0309: include_str!("./error_codes/E0309.md"), +E0310: include_str!("./error_codes/E0310.md"), +E0312: include_str!("./error_codes/E0312.md"), +E0317: include_str!("./error_codes/E0317.md"), +E0321: include_str!("./error_codes/E0321.md"), +E0322: include_str!("./error_codes/E0322.md"), +E0323: include_str!("./error_codes/E0323.md"), +E0324: include_str!("./error_codes/E0324.md"), +E0325: include_str!("./error_codes/E0325.md"), +E0326: include_str!("./error_codes/E0326.md"), +E0328: include_str!("./error_codes/E0328.md"), +E0329: include_str!("./error_codes/E0329.md"), +E0364: include_str!("./error_codes/E0364.md"), +E0365: include_str!("./error_codes/E0365.md"), +E0366: include_str!("./error_codes/E0366.md"), +E0367: include_str!("./error_codes/E0367.md"), +E0368: include_str!("./error_codes/E0368.md"), +E0369: include_str!("./error_codes/E0369.md"), +E0370: include_str!("./error_codes/E0370.md"), +E0371: include_str!("./error_codes/E0371.md"), +E0373: include_str!("./error_codes/E0373.md"), +E0374: include_str!("./error_codes/E0374.md"), +E0375: include_str!("./error_codes/E0375.md"), +E0376: include_str!("./error_codes/E0376.md"), +E0378: include_str!("./error_codes/E0378.md"), +E0379: include_str!("./error_codes/E0379.md"), +E0380: include_str!("./error_codes/E0380.md"), +E0381: include_str!("./error_codes/E0381.md"), +E0382: include_str!("./error_codes/E0382.md"), +E0383: include_str!("./error_codes/E0383.md"), +E0384: include_str!("./error_codes/E0384.md"), +E0386: include_str!("./error_codes/E0386.md"), +E0387: include_str!("./error_codes/E0387.md"), +E0388: include_str!("./error_codes/E0388.md"), +E0389: include_str!("./error_codes/E0389.md"), +E0390: include_str!("./error_codes/E0390.md"), +E0391: include_str!("./error_codes/E0391.md"), +E0392: include_str!("./error_codes/E0392.md"), +E0393: include_str!("./error_codes/E0393.md"), +E0398: include_str!("./error_codes/E0398.md"), +E0399: include_str!("./error_codes/E0399.md"), +E0401: include_str!("./error_codes/E0401.md"), +E0403: include_str!("./error_codes/E0403.md"), +E0404: include_str!("./error_codes/E0404.md"), +E0405: include_str!("./error_codes/E0405.md"), +E0407: include_str!("./error_codes/E0407.md"), +E0408: include_str!("./error_codes/E0408.md"), +E0409: include_str!("./error_codes/E0409.md"), +E0411: include_str!("./error_codes/E0411.md"), +E0412: include_str!("./error_codes/E0412.md"), +E0415: include_str!("./error_codes/E0415.md"), +E0416: include_str!("./error_codes/E0416.md"), +E0422: include_str!("./error_codes/E0422.md"), +E0423: include_str!("./error_codes/E0423.md"), +E0424: include_str!("./error_codes/E0424.md"), +E0425: include_str!("./error_codes/E0425.md"), +E0426: include_str!("./error_codes/E0426.md"), +E0428: include_str!("./error_codes/E0428.md"), +E0429: include_str!("./error_codes/E0429.md"), +E0430: include_str!("./error_codes/E0430.md"), +E0431: include_str!("./error_codes/E0431.md"), +E0432: include_str!("./error_codes/E0432.md"), +E0433: include_str!("./error_codes/E0433.md"), +E0434: include_str!("./error_codes/E0434.md"), +E0435: include_str!("./error_codes/E0435.md"), +E0436: include_str!("./error_codes/E0436.md"), +E0437: include_str!("./error_codes/E0437.md"), +E0438: include_str!("./error_codes/E0438.md"), +E0439: include_str!("./error_codes/E0439.md"), +E0445: include_str!("./error_codes/E0445.md"), +E0446: include_str!("./error_codes/E0446.md"), +E0447: include_str!("./error_codes/E0447.md"), +E0448: include_str!("./error_codes/E0448.md"), +E0449: include_str!("./error_codes/E0449.md"), +E0451: include_str!("./error_codes/E0451.md"), +E0452: include_str!("./error_codes/E0452.md"), +E0453: include_str!("./error_codes/E0453.md"), +E0454: include_str!("./error_codes/E0454.md"), +E0455: include_str!("./error_codes/E0455.md"), +E0458: include_str!("./error_codes/E0458.md"), +E0459: include_str!("./error_codes/E0459.md"), +E0463: include_str!("./error_codes/E0463.md"), +E0466: include_str!("./error_codes/E0466.md"), +E0468: include_str!("./error_codes/E0468.md"), +E0469: include_str!("./error_codes/E0469.md"), +E0478: include_str!("./error_codes/E0478.md"), +E0491: include_str!("./error_codes/E0491.md"), +E0492: include_str!("./error_codes/E0492.md"), +E0493: include_str!("./error_codes/E0493.md"), +E0495: include_str!("./error_codes/E0495.md"), +E0496: include_str!("./error_codes/E0496.md"), +E0497: include_str!("./error_codes/E0497.md"), +E0499: include_str!("./error_codes/E0499.md"), +E0500: include_str!("./error_codes/E0500.md"), +E0501: include_str!("./error_codes/E0501.md"), +E0502: include_str!("./error_codes/E0502.md"), +E0503: include_str!("./error_codes/E0503.md"), +E0504: include_str!("./error_codes/E0504.md"), +E0505: include_str!("./error_codes/E0505.md"), +E0506: include_str!("./error_codes/E0506.md"), +E0507: include_str!("./error_codes/E0507.md"), +E0508: include_str!("./error_codes/E0508.md"), +E0509: include_str!("./error_codes/E0509.md"), +E0510: include_str!("./error_codes/E0510.md"), +E0511: include_str!("./error_codes/E0511.md"), +E0512: include_str!("./error_codes/E0512.md"), +E0515: include_str!("./error_codes/E0515.md"), +E0516: include_str!("./error_codes/E0516.md"), +E0517: include_str!("./error_codes/E0517.md"), +E0518: include_str!("./error_codes/E0518.md"), +E0520: include_str!("./error_codes/E0520.md"), +E0522: include_str!("./error_codes/E0522.md"), +E0524: include_str!("./error_codes/E0524.md"), +E0525: include_str!("./error_codes/E0525.md"), +E0527: include_str!("./error_codes/E0527.md"), +E0528: include_str!("./error_codes/E0528.md"), +E0529: include_str!("./error_codes/E0529.md"), +E0530: include_str!("./error_codes/E0530.md"), +E0531: include_str!("./error_codes/E0531.md"), +E0532: include_str!("./error_codes/E0532.md"), +E0533: include_str!("./error_codes/E0533.md"), +E0534: include_str!("./error_codes/E0534.md"), +E0535: include_str!("./error_codes/E0535.md"), +E0536: include_str!("./error_codes/E0536.md"), +E0537: include_str!("./error_codes/E0537.md"), +E0538: include_str!("./error_codes/E0538.md"), +E0541: include_str!("./error_codes/E0541.md"), +E0550: include_str!("./error_codes/E0550.md"), +E0551: include_str!("./error_codes/E0551.md"), +E0552: include_str!("./error_codes/E0552.md"), +E0554: include_str!("./error_codes/E0554.md"), +E0556: include_str!("./error_codes/E0556.md"), +E0557: include_str!("./error_codes/E0557.md"), +E0559: include_str!("./error_codes/E0559.md"), +E0560: include_str!("./error_codes/E0560.md"), +E0561: include_str!("./error_codes/E0561.md"), +E0562: include_str!("./error_codes/E0562.md"), +E0565: include_str!("./error_codes/E0565.md"), +E0566: include_str!("./error_codes/E0566.md"), +E0567: include_str!("./error_codes/E0567.md"), +E0568: include_str!("./error_codes/E0568.md"), +E0569: include_str!("./error_codes/E0569.md"), +E0570: include_str!("./error_codes/E0570.md"), +E0571: include_str!("./error_codes/E0571.md"), +E0572: include_str!("./error_codes/E0572.md"), +E0573: include_str!("./error_codes/E0573.md"), +E0574: include_str!("./error_codes/E0574.md"), +E0575: include_str!("./error_codes/E0575.md"), +E0576: include_str!("./error_codes/E0576.md"), +E0577: include_str!("./error_codes/E0577.md"), +E0578: include_str!("./error_codes/E0578.md"), +E0579: include_str!("./error_codes/E0579.md"), +E0580: include_str!("./error_codes/E0580.md"), +E0581: include_str!("./error_codes/E0581.md"), +E0582: include_str!("./error_codes/E0582.md"), +E0583: include_str!("./error_codes/E0583.md"), +E0584: include_str!("./error_codes/E0584.md"), +E0585: include_str!("./error_codes/E0585.md"), +E0586: include_str!("./error_codes/E0586.md"), +E0587: include_str!("./error_codes/E0587.md"), +E0588: include_str!("./error_codes/E0588.md"), +E0589: include_str!("./error_codes/E0589.md"), +E0590: include_str!("./error_codes/E0590.md"), +E0591: include_str!("./error_codes/E0591.md"), +E0592: include_str!("./error_codes/E0592.md"), +E0593: include_str!("./error_codes/E0593.md"), +E0594: include_str!("./error_codes/E0594.md"), +E0595: include_str!("./error_codes/E0595.md"), +E0596: include_str!("./error_codes/E0596.md"), +E0597: include_str!("./error_codes/E0597.md"), +E0599: include_str!("./error_codes/E0599.md"), +E0600: include_str!("./error_codes/E0600.md"), +E0601: include_str!("./error_codes/E0601.md"), +E0602: include_str!("./error_codes/E0602.md"), +E0603: include_str!("./error_codes/E0603.md"), +E0604: include_str!("./error_codes/E0604.md"), +E0605: include_str!("./error_codes/E0605.md"), +E0606: include_str!("./error_codes/E0606.md"), +E0607: include_str!("./error_codes/E0607.md"), +E0608: include_str!("./error_codes/E0608.md"), +E0609: include_str!("./error_codes/E0609.md"), +E0610: include_str!("./error_codes/E0610.md"), +E0614: include_str!("./error_codes/E0614.md"), +E0615: include_str!("./error_codes/E0615.md"), +E0616: include_str!("./error_codes/E0616.md"), +E0617: include_str!("./error_codes/E0617.md"), +E0618: include_str!("./error_codes/E0618.md"), +E0619: include_str!("./error_codes/E0619.md"), +E0620: include_str!("./error_codes/E0620.md"), +E0621: include_str!("./error_codes/E0621.md"), +E0622: include_str!("./error_codes/E0622.md"), +E0623: include_str!("./error_codes/E0623.md"), +E0624: include_str!("./error_codes/E0624.md"), +E0626: include_str!("./error_codes/E0626.md"), +E0631: include_str!("./error_codes/E0631.md"), +E0633: include_str!("./error_codes/E0633.md"), +E0635: include_str!("./error_codes/E0635.md"), +E0636: include_str!("./error_codes/E0636.md"), +E0638: include_str!("./error_codes/E0638.md"), +E0639: include_str!("./error_codes/E0639.md"), +E0641: include_str!("./error_codes/E0641.md"), +E0642: include_str!("./error_codes/E0642.md"), +E0643: include_str!("./error_codes/E0643.md"), +E0644: include_str!("./error_codes/E0644.md"), +E0646: include_str!("./error_codes/E0646.md"), +E0647: include_str!("./error_codes/E0647.md"), +E0648: include_str!("./error_codes/E0648.md"), +E0658: include_str!("./error_codes/E0658.md"), +E0659: include_str!("./error_codes/E0659.md"), +E0660: include_str!("./error_codes/E0660.md"), +E0661: include_str!("./error_codes/E0661.md"), +E0662: include_str!("./error_codes/E0662.md"), +E0663: include_str!("./error_codes/E0663.md"), +E0664: include_str!("./error_codes/E0664.md"), +E0665: include_str!("./error_codes/E0665.md"), +E0666: include_str!("./error_codes/E0666.md"), +E0668: include_str!("./error_codes/E0668.md"), +E0669: include_str!("./error_codes/E0669.md"), +E0670: include_str!("./error_codes/E0670.md"), +E0671: include_str!("./error_codes/E0671.md"), +E0689: include_str!("./error_codes/E0689.md"), +E0690: include_str!("./error_codes/E0690.md"), +E0691: include_str!("./error_codes/E0691.md"), +E0692: include_str!("./error_codes/E0692.md"), +E0695: include_str!("./error_codes/E0695.md"), +E0697: include_str!("./error_codes/E0697.md"), +E0698: include_str!("./error_codes/E0698.md"), +E0699: include_str!("./error_codes/E0699.md"), +E0700: include_str!("./error_codes/E0700.md"), +E0701: include_str!("./error_codes/E0701.md"), +E0704: include_str!("./error_codes/E0704.md"), +E0705: include_str!("./error_codes/E0705.md"), +E0706: include_str!("./error_codes/E0706.md"), +E0712: include_str!("./error_codes/E0712.md"), +E0713: include_str!("./error_codes/E0713.md"), +E0714: include_str!("./error_codes/E0714.md"), +E0715: include_str!("./error_codes/E0715.md"), +E0716: include_str!("./error_codes/E0716.md"), +E0718: include_str!("./error_codes/E0718.md"), +E0720: include_str!("./error_codes/E0720.md"), +E0723: include_str!("./error_codes/E0723.md"), +E0725: include_str!("./error_codes/E0725.md"), +E0728: include_str!("./error_codes/E0728.md"), +E0729: include_str!("./error_codes/E0729.md"), +E0730: include_str!("./error_codes/E0730.md"), +E0731: include_str!("./error_codes/E0731.md"), +E0732: include_str!("./error_codes/E0732.md"), +E0733: include_str!("./error_codes/E0733.md"), +E0734: include_str!("./error_codes/E0734.md"), +E0735: include_str!("./error_codes/E0735.md"), +E0736: include_str!("./error_codes/E0736.md"), +E0737: include_str!("./error_codes/E0737.md"), +E0738: include_str!("./error_codes/E0738.md"), +E0740: include_str!("./error_codes/E0740.md"), +E0741: include_str!("./error_codes/E0741.md"), +E0742: include_str!("./error_codes/E0742.md"), +E0743: include_str!("./error_codes/E0743.md"), +E0744: include_str!("./error_codes/E0744.md"), +E0745: include_str!("./error_codes/E0745.md"), +; +// E0006, // merged with E0005 +// E0008, // cannot bind by-move into a pattern guard +// E0035, merged into E0087/E0089 +// E0036, merged into E0087/E0089 +// E0068, +// E0085, +// E0086, +// E0101, // replaced with E0282 +// E0102, // replaced with E0282 +// E0103, +// E0104, +// E0122, // bounds in type aliases are ignored, turned into proper lint +// E0123, +// E0127, +// E0129, +// E0134, +// E0135, +// E0141, +// E0153, unused error code +// E0157, unused error code +// E0159, // use of trait `{}` as struct constructor +// E0163, // merged into E0071 +// E0167, +// E0168, +// E0172, // non-trait found in a type sum, moved to resolve +// E0173, // manual implementations of unboxed closure traits are experimental +// E0174, +// E0182, // merged into E0229 + E0183, +// E0187, // cannot infer the kind of the closure +// E0188, // can not cast an immutable reference to a mutable pointer +// E0189, // deprecated: can only cast a boxed pointer to a boxed object +// E0190, // deprecated: can only cast a &-pointer to an &-object +// E0194, // merged into E0403 +// E0196, // cannot determine a type for this closure + E0208, +// E0209, // builtin traits can only be implemented on structs or enums + E0212, // cannot extract an associated type from a higher-ranked trait bound +// E0213, // associated types are not accepted in this context +// E0215, // angle-bracket notation is not stable with `Fn` +// E0216, // parenthetical notation is only stable with `Fn` +// E0217, // ambiguous associated type, defined in multiple supertraits +// E0218, // no associated type defined +// E0219, // associated type defined in higher-ranked supertrait +// E0222, // Error code E0045 (variadic function must have C or cdecl calling + // convention) duplicate + E0224, // at least one non-builtin train is required for an object type + E0226, // only a single explicit lifetime bound is permitted + E0227, // ambiguous lifetime bound, explicit lifetime bound required + E0228, // explicit lifetime bound required +// E0233, +// E0234, +// E0235, // structure constructor specifies a structure of type but +// E0236, // no lang item for range syntax +// E0237, // no lang item for range syntax +// E0238, // parenthesized parameters may only be used with a trait +// E0239, // `next` method of `Iterator` trait has unexpected type +// E0240, +// E0241, +// E0242, +// E0245, // not a trait +// E0246, // invalid recursive type +// E0247, +// E0248, // value used as a type, now reported earlier during resolution + // as E0412 +// E0249, +// E0257, +// E0258, +// E0272, // on_unimplemented #0 +// E0273, // on_unimplemented #1 +// E0274, // on_unimplemented #2 +// E0278, // requirement is not satisfied + E0279, // requirement is not satisfied + E0280, // requirement is not satisfied +// E0285, // overflow evaluation builtin bounds +// E0296, // replaced with a generic attribute input check +// E0298, // cannot compare constants +// E0299, // mismatched types between arms +// E0300, // unexpanded macro +// E0304, // expected signed integer constant +// E0305, // expected constant + E0311, // thing may not live long enough + E0313, // lifetime of borrowed pointer outlives lifetime of captured + // variable + E0314, // closure outlives stack frame + E0315, // cannot invoke closure outside of its lifetime + E0316, // nested quantification of lifetimes +// E0319, // trait impls for defaulted traits allowed just for structs/enums + E0320, // recursive overflow during dropck +// E0372, // coherence not object safe + E0377, // the trait `CoerceUnsized` may only be implemented for a coercion + // between structures with the same definition +// E0385, // {} in an aliasable location +// E0402, // cannot use an outer type parameter in this context +// E0406, merged into 420 +// E0410, merged into 408 +// E0413, merged into 530 +// E0414, merged into 530 +// E0417, merged into 532 +// E0418, merged into 532 +// E0419, merged into 531 +// E0420, merged into 532 +// E0421, merged into 531 +// E0427, merged into 530 + E0456, // plugin `..` is not available for triple `..` + E0457, // plugin `..` only found in rlib format, but must be available... + E0460, // found possibly newer version of crate `..` + E0461, // couldn't find crate `..` with expected target triple .. + E0462, // found staticlib `..` instead of rlib or dylib + E0464, // multiple matching crates for `..` + E0465, // multiple .. candidates for `..` found +// E0467, removed +// E0470, removed +// E0471, // constant evaluation error (in pattern) + E0472, // asm! is unsupported on this target + E0473, // dereference of reference outside its lifetime + E0474, // captured variable `..` does not outlive the enclosing closure + E0475, // index of slice outside its lifetime + E0476, // lifetime of the source pointer does not outlive lifetime bound... + E0477, // the type `..` does not fulfill the required lifetime... + E0479, // the type `..` (provided as the value of a type parameter) is... + E0480, // lifetime of method receiver does not outlive the method call + E0481, // lifetime of function argument does not outlive the function call + E0482, // lifetime of return value does not outlive the function call + E0483, // lifetime of operand does not outlive the operation + E0484, // reference is not valid at the time of borrow + E0485, // automatically reference is not valid at the time of borrow + E0486, // type of expression contains references that are not valid during.. + E0487, // unsafe use of destructor: destructor might be called while... + E0488, // lifetime of variable does not enclose its declaration + E0489, // type/lifetime parameter not in scope here + E0490, // a value of type `..` is borrowed for too long + E0498, // malformed plugin attribute + E0514, // metadata version mismatch + E0519, // local crate and dependency have same (crate-name, disambiguator) + // two dependencies have same (crate-name, disambiguator) but different SVH + E0521, // borrowed data escapes outside of closure + E0523, +// E0526, // shuffle indices are not constant + E0539, // incorrect meta item + E0540, // multiple rustc_deprecated attributes + E0542, // missing 'since' + E0543, // missing 'reason' + E0544, // multiple stability levels + E0545, // incorrect 'issue' + E0546, // missing 'feature' + E0547, // missing 'issue' +// E0548, // replaced with a generic attribute input check + // rustc_deprecated attribute must be paired with either stable or unstable + // attribute + E0549, + E0553, // multiple rustc_const_unstable attributes +// E0555, // replaced with a generic attribute input check +// E0558, // replaced with a generic attribute input check +// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 +// E0564, // only named lifetimes are allowed in `impl Trait`, + // but `{}` was found in the type `{}` +// E0598, // lifetime of {} is too short to guarantee its contents can be... +// E0611, // merged into E0616 +// E0612, // merged into E0609 +// E0613, // Removed (merged with E0609) + E0625, // thread-local statics cannot be accessed at compile-time + E0627, // yield statement outside of generator literal + E0628, // generators cannot have explicit parameters + E0629, // missing 'feature' (rustc_const_unstable) + // rustc_const_unstable attribute must be paired with stable/unstable + // attribute + E0630, + E0632, // cannot provide explicit generic arguments when `impl Trait` is + // used in argument position + E0634, // type has conflicting packed representaton hints + E0637, // "'_" is not a valid lifetime bound + E0640, // infer outlives requirements +// E0645, // trait aliases not finished + E0657, // `impl Trait` can only capture lifetimes bound at the fn level + E0667, // `impl Trait` in projections + E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax + E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders + E0693, // incorrect `repr(align)` attribute format +// E0694, // an unknown tool name found in scoped attributes + E0696, // `continue` pointing to a labeled block +// E0702, // replaced with a generic attribute input check + E0703, // invalid ABI +// E0707, // multiple elided lifetimes used in arguments of `async fn` + E0708, // `async` non-`move` closures with parameters are not currently + // supported +// E0709, // multiple different lifetimes used in arguments of `async fn` + E0710, // an unknown tool name found in scoped lint + E0711, // a feature has been declared with conflicting stability attributes + E0717, // rustc_promotable without stability attribute + E0719, // duplicate values for associated type binding +// E0721, // `await` keyword + E0722, // Malformed `#[optimize]` attribute + E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions + E0726, // non-explicit (not `'_`) elided lifetime in unsupported position + E0727, // `async` generators are not yet supported + E0739, // invalid track_caller application/syntax +} diff --git a/src/librustc_error_codes/error_codes/E0001.md b/src/librustc_error_codes/error_codes/E0001.md new file mode 100644 index 0000000000..90756780d1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0001.md @@ -0,0 +1,24 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error suggests that the expression arm corresponding to the noted pattern +will never be reached as for all possible values of the expression being +matched, one of the preceding patterns will match. + +This means that perhaps some of the preceding patterns are too general, this +one is too specific or the ordering is incorrect. + +For example, the following `match` block has too many arms: + +``` +match Some(0) { + Some(bar) => {/* ... */} + x => {/* ... */} // This handles the `None` case + _ => {/* ... */} // All possible cases have already been handled +} +``` + +`match` blocks have their patterns matched in order, so, for example, putting +a wildcard arm above a more specific arm will make the latter arm irrelevant. + +Ensure the ordering of the match arm is correct and remove any superfluous +arms. diff --git a/src/librustc_error_codes/error_codes/E0002.md b/src/librustc_error_codes/error_codes/E0002.md new file mode 100644 index 0000000000..5cb59da10e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0002.md @@ -0,0 +1,29 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error indicates that an empty match expression is invalid because the type +it is matching on is non-empty (there exist values of this type). In safe code +it is impossible to create an instance of an empty type, so empty match +expressions are almost never desired. This error is typically fixed by adding +one or more cases to the match expression. + +An example of an empty type is `enum Empty { }`. So, the following will work: + +``` +enum Empty {} + +fn foo(x: Empty) { + match x { + // empty + } +} +``` + +However, this won't: + +```compile_fail +fn foo(x: Option) { + match x { + // empty + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0004.md b/src/librustc_error_codes/error_codes/E0004.md new file mode 100644 index 0000000000..b79ef5fd8c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0004.md @@ -0,0 +1,46 @@ +This error indicates that the compiler cannot guarantee a matching pattern for +one or more possible inputs to a match expression. Guaranteed matches are +required in order to assign values to match expressions, or alternatively, +determine the flow of execution. + +Erroneous code example: + +```compile_fail,E0004 +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +let x = Terminator::HastaLaVistaBaby; + +match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered + Terminator::TalkToMyHand => {} +} +``` + +If you encounter this error you must alter your patterns so that every possible +value of the input type is matched. For types with a small number of variants +(like enums) you should probably cover all cases explicitly. Alternatively, the +underscore `_` wildcard pattern can be added after all other patterns to match +"anything else". Example: + +``` +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +let x = Terminator::HastaLaVistaBaby; + +match x { + Terminator::TalkToMyHand => {} + Terminator::HastaLaVistaBaby => {} +} + +// or: + +match x { + Terminator::TalkToMyHand => {} + _ => {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0005.md b/src/librustc_error_codes/error_codes/E0005.md new file mode 100644 index 0000000000..e2e7db5082 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0005.md @@ -0,0 +1,30 @@ +Patterns used to bind names must be irrefutable, that is, they must guarantee +that a name will be extracted in all cases. + +Erroneous code example: + +```compile_fail,E0005 +let x = Some(1); +let Some(y) = x; +// error: refutable pattern in local binding: `None` not covered +``` + +If you encounter this error you probably need to use a `match` or `if let` to +deal with the possibility of failure. Example: + +``` +let x = Some(1); + +match x { + Some(y) => { + // do something + }, + None => {} +} + +// or: + +if let Some(y) = x { + // do something +} +``` diff --git a/src/librustc_error_codes/error_codes/E0007.md b/src/librustc_error_codes/error_codes/E0007.md new file mode 100644 index 0000000000..2be7870d5a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0007.md @@ -0,0 +1,18 @@ +This error indicates that the bindings in a match arm would require a value to +be moved into more than one location, thus violating unique ownership. Code +like the following is invalid as it requires the entire `Option` to be +moved into a variable called `op_string` while simultaneously requiring the +inner `String` to be moved into a variable called `s`. + +Erroneous code example: + +```compile_fail,E0007 +let x = Some("s".to_string()); + +match x { + op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings + None => {}, +} +``` + +See also the error E0303. diff --git a/src/librustc_error_codes/error_codes/E0009.md b/src/librustc_error_codes/error_codes/E0009.md new file mode 100644 index 0000000000..abb7fe41ab --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0009.md @@ -0,0 +1,48 @@ +In a pattern, all values that don't implement the `Copy` trait have to be bound +the same way. The goal here is to avoid binding simultaneously by-move and +by-ref. + +This limitation may be removed in a future version of Rust. + +Erroneous code example: + +```compile_fail,E0009 +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((y, ref z)) => {}, // error: cannot bind by-move and by-ref in the + // same pattern + None => panic!() +} +``` + +You have two solutions: + +Solution #1: Bind the pattern's values the same way. + +``` +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((ref y, ref z)) => {}, + // or Some((y, z)) => {} + None => panic!() +} +``` + +Solution #2: Implement the `Copy` trait for the `X` structure. + +However, please keep in mind that the first solution should be preferred. + +``` +#[derive(Clone, Copy)] +struct X { x: (), } + +let x = Some((X { x: () }, X { x: () })); +match x { + Some((y, ref z)) => {}, + None => panic!() +} +``` diff --git a/src/librustc_error_codes/error_codes/E0010.md b/src/librustc_error_codes/error_codes/E0010.md new file mode 100644 index 0000000000..71c790e102 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0010.md @@ -0,0 +1,11 @@ +The value of statics and constants must be known at compile time, and they live +for the entire lifetime of a program. Creating a boxed value allocates memory on +the heap at runtime, and therefore cannot be done at compile time. + +Erroneous code example: + +```compile_fail,E0010 +#![feature(box_syntax)] + +const CON : Box = box 0; +``` diff --git a/src/librustc_error_codes/error_codes/E0013.md b/src/librustc_error_codes/error_codes/E0013.md new file mode 100644 index 0000000000..8de177590e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0013.md @@ -0,0 +1,18 @@ +Static and const variables can refer to other const variables. But a const +variable cannot refer to a static variable. + +Erroneous code example: + +```compile_fail,E0013 +static X: i32 = 42; +const Y: i32 = X; +``` + +In this example, `Y` cannot refer to `X` here. To fix this, the value can be +extracted as a const and then used: + +``` +const A: i32 = 42; +static X: i32 = A; +const Y: i32 = A; +``` diff --git a/src/librustc_error_codes/error_codes/E0014.md b/src/librustc_error_codes/error_codes/E0014.md new file mode 100644 index 0000000000..2c69957e9f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0014.md @@ -0,0 +1,20 @@ +#### Note: this error code is no longer emitted by the compiler. + +Constants can only be initialized by a constant value or, in a future +version of Rust, a call to a const function. This error indicates the use +of a path (like a::b, or x) denoting something other than one of these +allowed items. + +Erroneous code example: + +``` +const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function! +``` + +To avoid it, you have to replace the non-constant value: + +``` +const FOO: i32 = { const X : i32 = 0; X }; +// or even: +const FOO2: i32 = { 0 }; // but brackets are useless here +``` diff --git a/src/librustc_error_codes/error_codes/E0015.md b/src/librustc_error_codes/error_codes/E0015.md new file mode 100644 index 0000000000..021a0219d1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0015.md @@ -0,0 +1,33 @@ +A constant item was initialized with something that is not a constant +expression. + +Erroneous code example: + +```compile_fail,E0015 +fn create_some() -> Option { + Some(1) +} + +const FOO: Option = create_some(); // error! +``` + +The only functions that can be called in static or constant expressions are +`const` functions, and struct/enum constructors. + +To fix this error, you can declare `create_some` as a constant function: + +``` +const fn create_some() -> Option { // declared as a const function + Some(1) +} + +const FOO: Option = create_some(); // ok! + +// These are also working: +struct Bar { + x: u8, +} + +const OTHER_FOO: Option = Some(1); +const BAR: Bar = Bar {x: 1}; +``` diff --git a/src/librustc_error_codes/error_codes/E0019.md b/src/librustc_error_codes/error_codes/E0019.md new file mode 100644 index 0000000000..7832468a53 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0019.md @@ -0,0 +1,36 @@ +A function call isn't allowed in the const's initialization expression +because the expression's value must be known at compile-time. + +Erroneous code example: + +```compile_fail,E0019 +#![feature(box_syntax)] + +fn main() { + struct MyOwned; + + static STATIC11: Box = box MyOwned; // error! +} +``` + +Remember: you can't use a function call inside a const's initialization +expression! However, you can totally use it anywhere else: + +``` +enum Test { + V1 +} + +impl Test { + fn func(&self) -> i32 { + 12 + } +} + +fn main() { + const FOO: Test = Test::V1; + + FOO.func(); // here is good + let x = FOO.func(); // or even here! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0023.md b/src/librustc_error_codes/error_codes/E0023.md new file mode 100644 index 0000000000..c1d85705da --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0023.md @@ -0,0 +1,57 @@ +A pattern attempted to extract an incorrect number of fields from a variant. + +Erroneous code example: + +```compile_fail,E0023 +enum Fruit { + Apple(String, String), + Pear(u32), +} + +let x = Fruit::Apple(String::new(), String::new()); + +match x { + Fruit::Apple(a) => {}, // error! + _ => {} +} +``` + +A pattern used to match against an enum variant must provide a sub-pattern for +each field of the enum variant. + +Here the `Apple` variant has two fields, and should be matched against like so: + +``` +enum Fruit { + Apple(String, String), + Pear(u32), +} + +let x = Fruit::Apple(String::new(), String::new()); + +// Correct. +match x { + Fruit::Apple(a, b) => {}, + _ => {} +} +``` + +Matching with the wrong number of fields has no sensible interpretation: + +```compile_fail,E0023 +enum Fruit { + Apple(String, String), + Pear(u32), +} + +let x = Fruit::Apple(String::new(), String::new()); + +// Incorrect. +match x { + Fruit::Apple(a) => {}, + Fruit::Apple(a, b, c) => {}, +} +``` + +Check how many fields the enum was declared with and ensure that your pattern +uses the same number. diff --git a/src/librustc_error_codes/error_codes/E0025.md b/src/librustc_error_codes/error_codes/E0025.md new file mode 100644 index 0000000000..a85dc8c197 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0025.md @@ -0,0 +1,34 @@ +Each field of a struct can only be bound once in a pattern. + +Erroneous code example: + +```compile_fail,E0025 +struct Foo { + a: u8, + b: u8, +} + +fn main(){ + let x = Foo { a:1, b:2 }; + + let Foo { a: x, a: y } = x; + // error: field `a` bound multiple times in the pattern +} +``` + +Each occurrence of a field name binds the value of that field, so to fix this +error you will have to remove or alter the duplicate uses of the field name. +Perhaps you misspelled another field name? Example: + +``` +struct Foo { + a: u8, + b: u8, +} + +fn main(){ + let x = Foo { a:1, b:2 }; + + let Foo { a: x, b: y } = x; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0026.md b/src/librustc_error_codes/error_codes/E0026.md new file mode 100644 index 0000000000..72c575aabb --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0026.md @@ -0,0 +1,34 @@ +A struct pattern attempted to extract a non-existent field from a struct. + +Erroneous code example: + +```compile_fail,E0026 +struct Thing { + x: u32, + y: u32, +} + +let thing = Thing { x: 0, y: 0 }; + +match thing { + Thing { x, z } => {} // error: `Thing::z` field doesn't exist +} +``` + +If you are using shorthand field patterns but want to refer to the struct field +by a different name, you should rename it explicitly. Struct fields are +identified by the name used before the colon `:` so struct patterns should +resemble the declaration of the struct type being matched. + +``` +struct Thing { + x: u32, + y: u32, +} + +let thing = Thing { x: 0, y: 0 }; + +match thing { + Thing { x, y: z } => {} // we renamed `y` to `z` +} +``` diff --git a/src/librustc_error_codes/error_codes/E0027.md b/src/librustc_error_codes/error_codes/E0027.md new file mode 100644 index 0000000000..a8b1340ca0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0027.md @@ -0,0 +1,39 @@ +A pattern for a struct fails to specify a sub-pattern for every one of the +struct's fields. + +Erroneous code example: + +```compile_fail,E0027 +struct Dog { + name: String, + age: u32, +} + +let d = Dog { name: "Rusty".to_string(), age: 8 }; + +// This is incorrect. +match d { + Dog { age: x } => {} +} +``` + +To fix this error, ensure that each field from the struct's definition is +mentioned in the pattern, or use `..` to ignore unwanted fields. Example: + +``` +struct Dog { + name: String, + age: u32, +} + +let d = Dog { name: "Rusty".to_string(), age: 8 }; + +match d { + Dog { name: ref n, age: x } => {} +} + +// This is also correct (ignore unused fields). +match d { + Dog { age: x, .. } => {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0029.md b/src/librustc_error_codes/error_codes/E0029.md new file mode 100644 index 0000000000..d12d85b9b4 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0029.md @@ -0,0 +1,26 @@ +Something other than numbers and characters has been used for a range. + +Erroneous code example: + +```compile_fail,E0029 +let string = "salutations !"; + +// The ordering relation for strings cannot be evaluated at compile time, +// so this doesn't work: +match string { + "hello" ..= "world" => {} + _ => {} +} + +// This is a more general version, using a guard: +match string { + s if s >= "hello" && s <= "world" => {} + _ => {} +} +``` + +In a match expression, only numbers and characters can be matched against a +range. This is because the compiler checks that the range is non-empty at +compile-time, and is unable to evaluate arbitrary comparison functions. If you +want to capture values of an orderable type between two end-points, you can use +a guard. diff --git a/src/librustc_error_codes/error_codes/E0030.md b/src/librustc_error_codes/error_codes/E0030.md new file mode 100644 index 0000000000..67d496da5e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0030.md @@ -0,0 +1,15 @@ +When matching against a range, the compiler verifies that the range is +non-empty. Range patterns include both end-points, so this is equivalent to +requiring the start of the range to be less than or equal to the end of the +range. + +Erroneous code example: + +```compile_fail,E0030 +match 5u32 { + // This range is ok, albeit pointless. + 1 ..= 1 => {} + // This range is empty, and the compiler can tell. + 1000 ..= 5 => {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0033.md b/src/librustc_error_codes/error_codes/E0033.md new file mode 100644 index 0000000000..735a2d1f3f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0033.md @@ -0,0 +1,27 @@ +A trait type has been dereferenced. + +Erroneous code example: + +```compile_fail,E0033 +# trait SomeTrait { fn method_one(&self){} fn method_two(&self){} } +# impl SomeTrait for T {} +let trait_obj: &SomeTrait = &"some_value"; + +// This tries to implicitly dereference to create an unsized local variable. +let &invalid = trait_obj; + +// You can call methods without binding to the value being pointed at. +trait_obj.method_one(); +trait_obj.method_two(); +``` + +A pointer to a trait type cannot be implicitly dereferenced by a pattern. Every +trait defines a type, but because the size of trait implementers isn't fixed, +this type has no compile-time size. Therefore, all accesses to trait types must +be through pointers. If you encounter this error you should try to avoid +dereferencing the pointer. + +You can read more about trait objects in the [Trait Objects] section of the +Reference. + +[Trait Objects]: https://doc.rust-lang.org/reference/types.html#trait-objects diff --git a/src/librustc_error_codes/error_codes/E0034.md b/src/librustc_error_codes/error_codes/E0034.md new file mode 100644 index 0000000000..2a21f3441c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0034.md @@ -0,0 +1,86 @@ +The compiler doesn't know what method to call because more than one method +has the same prototype. + +Erroneous code example: + +```compile_fail,E0034 +struct Test; + +trait Trait1 { + fn foo(); +} + +trait Trait2 { + fn foo(); +} + +impl Trait1 for Test { fn foo() {} } +impl Trait2 for Test { fn foo() {} } + +fn main() { + Test::foo() // error, which foo() to call? +} +``` + +To avoid this error, you have to keep only one of them and remove the others. +So let's take our example and fix it: + +``` +struct Test; + +trait Trait1 { + fn foo(); +} + +impl Trait1 for Test { fn foo() {} } + +fn main() { + Test::foo() // and now that's good! +} +``` + +However, a better solution would be using fully explicit naming of type and +trait: + +``` +struct Test; + +trait Trait1 { + fn foo(); +} + +trait Trait2 { + fn foo(); +} + +impl Trait1 for Test { fn foo() {} } +impl Trait2 for Test { fn foo() {} } + +fn main() { + ::foo() +} +``` + +One last example: + +``` +trait F { + fn m(&self); +} + +trait G { + fn m(&self); +} + +struct X; + +impl F for X { fn m(&self) { println!("I am F"); } } +impl G for X { fn m(&self) { println!("I am G"); } } + +fn main() { + let f = X; + + F::m(&f); // it displays "I am F" + G::m(&f); // it displays "I am G" +} +``` diff --git a/src/librustc_error_codes/error_codes/E0038.md b/src/librustc_error_codes/error_codes/E0038.md new file mode 100644 index 0000000000..25e380b02e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0038.md @@ -0,0 +1,291 @@ +Trait objects like `Box` can only be constructed when certain +requirements are satisfied by the trait in question. + +Trait objects are a form of dynamic dispatch and use a dynamically sized type +for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a +type, as in `Box`, the inner type is 'unsized'. In such cases the boxed +pointer is a 'fat pointer' that contains an extra pointer to a table of methods +(among other things) for dynamic dispatch. This design mandates some +restrictions on the types of traits that are allowed to be used in trait +objects, which are collectively termed as 'object safety' rules. + +Attempting to create a trait object for a non object-safe trait will trigger +this error. + +There are various rules: + +### The trait cannot require `Self: Sized` + +When `Trait` is treated as a type, the type does not implement the special +`Sized` trait, because the type does not have a known size at compile time and +can only be accessed behind a pointer. Thus, if we have a trait like the +following: + +``` +trait Foo where Self: Sized { + +} +``` + +We cannot create an object of type `Box` or `&Foo` since in this case +`Self` would not be `Sized`. + +Generally, `Self: Sized` is used to indicate that the trait should not be used +as a trait object. If the trait comes from your own crate, consider removing +this restriction. + +### Method references the `Self` type in its parameters or return type + +This happens when a trait has a method like the following: + +``` +trait Trait { + fn foo(&self) -> Self; +} + +impl Trait for String { + fn foo(&self) -> Self { + "hi".to_owned() + } +} + +impl Trait for u8 { + fn foo(&self) -> Self { + 1 + } +} +``` + +(Note that `&self` and `&mut self` are okay, it's additional `Self` types which +cause this problem.) + +In such a case, the compiler cannot predict the return type of `foo()` in a +situation like the following: + +```compile_fail,E0038 +trait Trait { + fn foo(&self) -> Self; +} + +fn call_foo(x: Box) { + let y = x.foo(); // What type is y? + // ... +} +``` + +If only some methods aren't object-safe, you can add a `where Self: Sized` bound +on them to mark them as explicitly unavailable to trait objects. The +functionality will still be available to all other implementers, including +`Box` which is itself sized (assuming you `impl Trait for Box`). + +``` +trait Trait { + fn foo(&self) -> Self where Self: Sized; + // more functions +} +``` + +Now, `foo()` can no longer be called on a trait object, but you will now be +allowed to make a trait object, and that will be able to call any object-safe +methods. With such a bound, one can still call `foo()` on types implementing +that trait that aren't behind trait objects. + +### Method has generic type parameters + +As mentioned before, trait objects contain pointers to method tables. So, if we +have: + +``` +trait Trait { + fn foo(&self); +} + +impl Trait for String { + fn foo(&self) { + // implementation 1 + } +} + +impl Trait for u8 { + fn foo(&self) { + // implementation 2 + } +} +// ... +``` + +At compile time each implementation of `Trait` will produce a table containing +the various methods (and other items) related to the implementation. + +This works fine, but when the method gains generic parameters, we can have a +problem. + +Usually, generic parameters get _monomorphized_. For example, if I have + +``` +fn foo(x: T) { + // ... +} +``` + +The machine code for `foo::()`, `foo::()`, `foo::()`, or any +other type substitution is different. Hence the compiler generates the +implementation on-demand. If you call `foo()` with a `bool` parameter, the +compiler will only generate code for `foo::()`. When we have additional +type parameters, the number of monomorphized implementations the compiler +generates does not grow drastically, since the compiler will only generate an +implementation if the function is called with unparametrized substitutions +(i.e., substitutions where none of the substituted types are themselves +parametrized). + +However, with trait objects we have to make a table containing _every_ object +that implements the trait. Now, if it has type parameters, we need to add +implementations for every type that implements the trait, and there could +theoretically be an infinite number of types. + +For example, with: + +``` +trait Trait { + fn foo(&self, on: T); + // more methods +} + +impl Trait for String { + fn foo(&self, on: T) { + // implementation 1 + } +} + +impl Trait for u8 { + fn foo(&self, on: T) { + // implementation 2 + } +} + +// 8 more implementations +``` + +Now, if we have the following code: + +```compile_fail,E0038 +# trait Trait { fn foo(&self, on: T); } +# impl Trait for String { fn foo(&self, on: T) {} } +# impl Trait for u8 { fn foo(&self, on: T) {} } +# impl Trait for bool { fn foo(&self, on: T) {} } +# // etc. +fn call_foo(thing: Box) { + thing.foo(true); // this could be any one of the 8 types above + thing.foo(1); + thing.foo("hello"); +} +``` + +We don't just need to create a table of all implementations of all methods of +`Trait`, we need to create such a table, for each different type fed to +`foo()`. In this case this turns out to be (10 types implementing `Trait`)\*(3 +types being fed to `foo()`) = 30 implementations! + +With real world traits these numbers can grow drastically. + +To fix this, it is suggested to use a `where Self: Sized` bound similar to the +fix for the sub-error above if you do not intend to call the method with type +parameters: + +``` +trait Trait { + fn foo(&self, on: T) where Self: Sized; + // more methods +} +``` + +If this is not an option, consider replacing the type parameter with another +trait object (e.g., if `T: OtherTrait`, use `on: Box`). If the +number of types you intend to feed to this method is limited, consider manually +listing out the methods of different types. + +### Method has no receiver + +Methods that do not take a `self` parameter can't be called since there won't be +a way to get a pointer to the method table for them. + +``` +trait Foo { + fn foo() -> u8; +} +``` + +This could be called as `::foo()`, which would not be able to pick +an implementation. + +Adding a `Self: Sized` bound to these methods will generally make this compile. + +``` +trait Foo { + fn foo() -> u8 where Self: Sized; +} +``` + +### The trait cannot contain associated constants + +Just like static functions, associated constants aren't stored on the method +table. If the trait or any subtrait contain an associated constant, they cannot +be made into an object. + +```compile_fail,E0038 +trait Foo { + const X: i32; +} + +impl Foo {} +``` + +A simple workaround is to use a helper method instead: + +``` +trait Foo { + fn x(&self) -> i32; +} +``` + +### The trait cannot use `Self` as a type parameter in the supertrait listing + +This is similar to the second sub-error, but subtler. It happens in situations +like the following: + +```compile_fail,E0038 +trait Super {} + +trait Trait: Super { +} + +struct Foo; + +impl Super for Foo{} + +impl Trait for Foo {} + +fn main() { + let x: Box; +} +``` + +Here, the supertrait might have methods as follows: + +``` +trait Super { + fn get_a(&self) -> &A; // note that this is object safe! +} +``` + +If the trait `Trait` was deriving from something like `Super` or +`Super` (where `Foo` itself is `Foo`), this is okay, because given a type +`get_a()` will definitely return an object of that type. + +However, if it derives from `Super`, even though `Super` is object safe, +the method `get_a()` would return an object of unknown type when called on the +function. `Self` type parameters let us make object safe traits no longer safe, +so they are forbidden when specifying supertraits. + +There's no easy fix for this, generally code will need to be refactored so that +you no longer need to derive from `Super`. diff --git a/src/librustc_error_codes/error_codes/E0040.md b/src/librustc_error_codes/error_codes/E0040.md new file mode 100644 index 0000000000..1373f8340d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0040.md @@ -0,0 +1,39 @@ +It is not allowed to manually call destructors in Rust. + +Erroneous code example: + +```compile_fail,E0040 +struct Foo { + x: i32, +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +fn main() { + let mut x = Foo { x: -7 }; + x.drop(); // error: explicit use of destructor method +} +``` + +It is unnecessary to do this since `drop` is called automatically whenever a +value goes out of scope. However, if you really need to drop a value by hand, +you can use the `std::mem::drop` function: + +``` +struct Foo { + x: i32, +} +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} +fn main() { + let mut x = Foo { x: -7 }; + drop(x); // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0044.md b/src/librustc_error_codes/error_codes/E0044.md new file mode 100644 index 0000000000..635ff95329 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0044.md @@ -0,0 +1,15 @@ +You cannot use type or const parameters on foreign items. + +Example of erroneous code: + +```compile_fail,E0044 +extern { fn some_func(x: T); } +``` + +To fix this, replace the generic parameter with the specializations that you +need: + +``` +extern { fn some_func_i32(x: i32); } +extern { fn some_func_i64(x: i64); } +``` diff --git a/src/librustc_error_codes/error_codes/E0045.md b/src/librustc_error_codes/error_codes/E0045.md new file mode 100644 index 0000000000..143c693bf7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0045.md @@ -0,0 +1,21 @@ +Variadic parameters have been used on a non-C ABI function. + +Erroneous code example: + +```compile_fail,E0045 +#![feature(unboxed_closures)] + +extern "rust-call" { + fn foo(x: u8, ...); // error! +} +``` + +Rust only supports variadic parameters for interoperability with C code in its +FFI. As such, variadic parameters can only be used with functions which are +using the C ABI. To fix such code, put them in an extern "C" block: + +``` +extern "C" { + fn foo (x: u8, ...); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0046.md b/src/librustc_error_codes/error_codes/E0046.md new file mode 100644 index 0000000000..d8f95330c3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0046.md @@ -0,0 +1,31 @@ +Items are missing in a trait implementation. + +Erroneous code example: + +```compile_fail,E0046 +trait Foo { + fn foo(); +} + +struct Bar; + +impl Foo for Bar {} +// error: not all trait items implemented, missing: `foo` +``` + +When trying to make some type implement a trait `Foo`, you must, at minimum, +provide implementations for all of `Foo`'s required methods (meaning the +methods that do not have default implementations), as well as any required +trait items like associated types or constants. Example: + +``` +trait Foo { + fn foo(); +} + +struct Bar; + +impl Foo for Bar { + fn foo() {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0049.md b/src/librustc_error_codes/error_codes/E0049.md new file mode 100644 index 0000000000..a2034a3428 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0049.md @@ -0,0 +1,36 @@ +An attempted implementation of a trait method has the wrong number of type or +const parameters. + +Erroneous code example: + +```compile_fail,E0049 +trait Foo { + fn foo(x: T) -> Self; +} + +struct Bar; + +// error: method `foo` has 0 type parameters but its trait declaration has 1 +// type parameter +impl Foo for Bar { + fn foo(x: bool) -> Self { Bar } +} +``` + +For example, the `Foo` trait has a method `foo` with a type parameter `T`, +but the implementation of `foo` for the type `Bar` is missing this parameter. +To fix this error, they must have the same type parameters: + +``` +trait Foo { + fn foo(x: T) -> Self; +} + +struct Bar; + +impl Foo for Bar { + fn foo(x: T) -> Self { // ok! + Bar + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0050.md b/src/librustc_error_codes/error_codes/E0050.md new file mode 100644 index 0000000000..7b84c48007 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0050.md @@ -0,0 +1,36 @@ +An attempted implementation of a trait method has the wrong number of function +parameters. + +Erroneous code example: + +```compile_fail,E0050 +trait Foo { + fn foo(&self, x: u8) -> bool; +} + +struct Bar; + +// error: method `foo` has 1 parameter but the declaration in trait `Foo::foo` +// has 2 +impl Foo for Bar { + fn foo(&self) -> bool { true } +} +``` + +For example, the `Foo` trait has a method `foo` with two function parameters +(`&self` and `u8`), but the implementation of `foo` for the type `Bar` omits +the `u8` parameter. To fix this error, they must have the same parameters: + +``` +trait Foo { + fn foo(&self, x: u8) -> bool; +} + +struct Bar; + +impl Foo for Bar { + fn foo(&self, x: u8) -> bool { // ok! + true + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0053.md b/src/librustc_error_codes/error_codes/E0053.md new file mode 100644 index 0000000000..cb2a8638a2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0053.md @@ -0,0 +1,21 @@ +The parameters of any trait method must match between a trait implementation +and the trait definition. + +Erroneous code example: + +```compile_fail,E0053 +trait Foo { + fn foo(x: u16); + fn bar(&self); +} + +struct Bar; + +impl Foo for Bar { + // error, expected u16, found i16 + fn foo(x: i16) { } + + // error, types differ in mutability + fn bar(&mut self) { } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0054.md b/src/librustc_error_codes/error_codes/E0054.md new file mode 100644 index 0000000000..c3eb375fbc --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0054.md @@ -0,0 +1,20 @@ +It is not allowed to cast to a bool. + +Erroneous code example: + +```compile_fail,E0054 +let x = 5; + +// Not allowed, won't compile +let x_is_nonzero = x as bool; +``` + +If you are trying to cast a numeric type to a bool, you can compare it with +zero instead: + +``` +let x = 5; + +// Ok +let x_is_nonzero = x != 0; +``` diff --git a/src/librustc_error_codes/error_codes/E0055.md b/src/librustc_error_codes/error_codes/E0055.md new file mode 100644 index 0000000000..d5b863081a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0055.md @@ -0,0 +1,28 @@ +During a method call, a value is automatically dereferenced as many times as +needed to make the value's type match the method's receiver. The catch is that +the compiler will only attempt to dereference a number of times up to the +recursion limit (which can be set via the `recursion_limit` attribute). + +For a somewhat artificial example: + +```compile_fail,E0055 +#![recursion_limit="5"] + +struct Foo; + +impl Foo { + fn foo(&self) {} +} + +fn main() { + let foo = Foo; + let ref_foo = &&&&&Foo; + + // error, reached the recursion limit while auto-dereferencing `&&&&&Foo` + ref_foo.foo(); +} +``` + +One fix may be to increase the recursion limit. Note that it is possible to +create an infinite recursion of dereferencing, in which case the only fix is to +somehow break the recursion. diff --git a/src/librustc_error_codes/error_codes/E0057.md b/src/librustc_error_codes/error_codes/E0057.md new file mode 100644 index 0000000000..bb5e4b48d2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0057.md @@ -0,0 +1,22 @@ +An invalid number of arguments was given when calling a closure. + +Erroneous code example: + +```compile_fail,E0057 +let f = |x| x * 3; +let a = f(); // invalid, too few parameters +let b = f(4); // this works! +let c = f(2, 3); // invalid, too many parameters +``` + +When invoking closures or other implementations of the function traits `Fn`, +`FnMut` or `FnOnce` using call notation, the number of parameters passed to the +function must match its definition. + +A generic function must be treated similarly: + +``` +fn foo(f: F) { + f(); // this is valid, but f(3) would not work +} +``` diff --git a/src/librustc_error_codes/error_codes/E0059.md b/src/librustc_error_codes/error_codes/E0059.md new file mode 100644 index 0000000000..b22edead25 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0059.md @@ -0,0 +1,25 @@ +The built-in function traits are generic over a tuple of the function arguments. +If one uses angle-bracket notation (`Fn<(T,), Output=U>`) instead of parentheses +(`Fn(T) -> U`) to denote the function trait, the type parameter should be a +tuple. Otherwise function call notation cannot be used and the trait will not be +implemented by closures. + +The most likely source of this error is using angle-bracket notation without +wrapping the function argument type into a tuple, for example: + +```compile_fail,E0059 +#![feature(unboxed_closures)] + +fn foo>(f: F) -> F::Output { f(3) } +``` + +It can be fixed by adjusting the trait bound like this: + +``` +#![feature(unboxed_closures)] + +fn foo>(f: F) -> F::Output { f(3) } +``` + +Note that `(T,)` always denotes the type of a 1-tuple containing an element of +type `T`. The comma is necessary for syntactic disambiguation. diff --git a/src/librustc_error_codes/error_codes/E0060.md b/src/librustc_error_codes/error_codes/E0060.md new file mode 100644 index 0000000000..7a07b8e7ed --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0060.md @@ -0,0 +1,36 @@ +External C functions are allowed to be variadic. However, a variadic function +takes a minimum number of arguments. For example, consider C's variadic `printf` +function: + +``` +use std::os::raw::{c_char, c_int}; + +extern "C" { + fn printf(_: *const c_char, ...) -> c_int; +} +``` + +Using this declaration, it must be called with at least one argument, so +simply calling `printf()` is invalid. But the following uses are allowed: + +``` +# #![feature(static_nobundle)] +# use std::os::raw::{c_char, c_int}; +# #[cfg_attr(all(windows, target_env = "msvc"), +# link(name = "legacy_stdio_definitions", kind = "static-nobundle"))] +# extern "C" { fn printf(_: *const c_char, ...) -> c_int; } +# fn main() { +unsafe { + use std::ffi::CString; + + let fmt = CString::new("test\n").unwrap(); + printf(fmt.as_ptr()); + + let fmt = CString::new("number = %d\n").unwrap(); + printf(fmt.as_ptr(), 3); + + let fmt = CString::new("%d, %d\n").unwrap(); + printf(fmt.as_ptr(), 10, 5); +} +# } +``` diff --git a/src/librustc_error_codes/error_codes/E0061.md b/src/librustc_error_codes/error_codes/E0061.md new file mode 100644 index 0000000000..143251c13b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0061.md @@ -0,0 +1,23 @@ +An invalid number of arguments was passed when calling a function. + +Erroneous code example: + +```compile_fail,E0061 +fn f(u: i32) {} + +f(); // error! +``` + +The number of arguments passed to a function must match the number of arguments +specified in the function signature. + +For example, a function like: + +``` +fn f(a: u16, b: &str) {} +``` + +Must always be called with exactly two arguments, e.g., `f(2, "test")`. + +Note that Rust does not have a notion of optional function arguments or +variadic functions (except for its C-FFI). diff --git a/src/librustc_error_codes/error_codes/E0062.md b/src/librustc_error_codes/error_codes/E0062.md new file mode 100644 index 0000000000..64fc027b88 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0062.md @@ -0,0 +1,30 @@ +A struct's or struct-like enum variant's field was specified more than once. + +Erroneous code example: + +```compile_fail,E0062 +struct Foo { + x: i32, +} + +fn main() { + let x = Foo { + x: 0, + x: 0, // error: field `x` specified more than once + }; +} +``` + +This error indicates that during an attempt to build a struct or struct-like +enum variant, one of the fields was specified more than once. Each field should +be specified exactly one time. Example: + +``` +struct Foo { + x: i32, +} + +fn main() { + let x = Foo { x: 0 }; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0063.md b/src/librustc_error_codes/error_codes/E0063.md new file mode 100644 index 0000000000..0e611deac4 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0063.md @@ -0,0 +1,27 @@ +A struct's or struct-like enum variant's field was not provided. + +Erroneous code example: + +```compile_fail,E0063 +struct Foo { + x: i32, + y: i32, +} + +fn main() { + let x = Foo { x: 0 }; // error: missing field: `y` +} +``` + +Each field should be specified exactly once. Example: + +``` +struct Foo { + x: i32, + y: i32, +} + +fn main() { + let x = Foo { x: 0, y: 0 }; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0067.md b/src/librustc_error_codes/error_codes/E0067.md new file mode 100644 index 0000000000..11041bb53e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0067.md @@ -0,0 +1,15 @@ +An invalid left-hand side expression was used on an assignment operation. + +Erroneous code example: + +```compile_fail,E0067 +12 += 1; // error! +``` + +You need to have a place expression to be able to assign it something. For +example: + +``` +let mut x: i8 = 12; +x += 1; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0069.md b/src/librustc_error_codes/error_codes/E0069.md new file mode 100644 index 0000000000..7367a5c092 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0069.md @@ -0,0 +1,14 @@ +The compiler found a function whose body contains a `return;` statement but +whose return type is not `()`. + +Erroneous code example: + +```compile_fail,E0069 +// error +fn foo() -> u8 { + return; +} +``` + +Since `return;` is just like `return ();`, there is a mismatch between the +function's return type and the value being returned. diff --git a/src/librustc_error_codes/error_codes/E0070.md b/src/librustc_error_codes/error_codes/E0070.md new file mode 100644 index 0000000000..97522af3da --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0070.md @@ -0,0 +1,49 @@ +An assignment operator was used on a non-place expression. + +Erroneous code examples: + +```compile_fail,E0070 +struct SomeStruct { + x: i32, + y: i32, +} + +const SOME_CONST: i32 = 12; + +fn some_other_func() {} + +fn some_function() { + SOME_CONST = 14; // error: a constant value cannot be changed! + 1 = 3; // error: 1 isn't a valid place! + some_other_func() = 4; // error: we cannot assign value to a function! + SomeStruct::x = 12; // error: SomeStruct a structure name but it is used + // like a variable! +} +``` + +The left-hand side of an assignment operator must be a place expression. A +place expression represents a memory location and can be a variable (with +optional namespacing), a dereference, an indexing expression or a field +reference. + +More details can be found in the [Expressions] section of the Reference. + +[Expressions]: https://doc.rust-lang.org/reference/expressions.html#places-rvalues-and-temporaries + +And now let's give working examples: + +``` +struct SomeStruct { + x: i32, + y: i32, +} +let mut s = SomeStruct { x: 0, y: 0 }; + +s.x = 3; // that's good ! + +// ... + +fn some_func(x: &mut i32) { + *x = 12; // that's good ! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0071.md b/src/librustc_error_codes/error_codes/E0071.md new file mode 100644 index 0000000000..bc2c03a022 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0071.md @@ -0,0 +1,27 @@ +A structure-literal syntax was used to create an item that is not a structure +or enum variant. + +Example of erroneous code: + +```compile_fail,E0071 +type U32 = u32; +let t = U32 { value: 4 }; // error: expected struct, variant or union type, + // found builtin type `u32` +``` + +To fix this, ensure that the name was correctly spelled, and that the correct +form of initializer was used. + +For example, the code above can be fixed to: + +``` +enum Foo { + FirstValue(i32) +} + +fn main() { + let u = Foo::FirstValue(0i32); + + let t = 4; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0072.md b/src/librustc_error_codes/error_codes/E0072.md new file mode 100644 index 0000000000..8f7749abab --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0072.md @@ -0,0 +1,37 @@ +A recursive type has infinite size because it doesn't have an indirection. + +Erroneous code example: + +```compile_fail,E0072 +struct ListNode { + head: u8, + tail: Option, // error: no indirection here so impossible to + // compute the type's size +} +``` + +When defining a recursive struct or enum, any use of the type being defined +from inside the definition must occur behind a pointer (like `Box`, `&` or +`Rc`). This is because structs and enums must have a well-defined size, and +without the pointer, the size of the type would need to be unbounded. + +In the example, the type cannot have a well-defined size, because it needs to be +arbitrarily large (since we would be able to nest `ListNode`s to any depth). +Specifically, + +```plain +size of `ListNode` = 1 byte for `head` + + 1 byte for the discriminant of the `Option` + + size of `ListNode` +``` + +One way to fix this is by wrapping `ListNode` in a `Box`, like so: + +``` +struct ListNode { + head: u8, + tail: Option>, +} +``` + +This works because `Box` is a pointer, so its size is well-known. diff --git a/src/librustc_error_codes/error_codes/E0073.md b/src/librustc_error_codes/error_codes/E0073.md new file mode 100644 index 0000000000..a5aea86ff2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0073.md @@ -0,0 +1,19 @@ +#### Note: this error code is no longer emitted by the compiler. + +You cannot define a struct (or enum) `Foo` that requires an instance of `Foo` +in order to make a new `Foo` value. This is because there would be no way a +first instance of `Foo` could be made to initialize another instance! + +Here's an example of a struct that has this problem: + +``` +struct Foo { x: Box } // error +``` + +One fix is to use `Option`, like so: + +``` +struct Foo { x: Option> } +``` + +Now it's possible to create at least one instance of `Foo`: `Foo { x: None }`. diff --git a/src/librustc_error_codes/error_codes/E0074.md b/src/librustc_error_codes/error_codes/E0074.md new file mode 100644 index 0000000000..e25dec7681 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0074.md @@ -0,0 +1,24 @@ +#### Note: this error code is no longer emitted by the compiler. + +When using the `#[simd]` attribute on a tuple struct, the components of the +tuple struct must all be of a concrete, nongeneric type so the compiler can +reason about how to use SIMD with them. This error will occur if the types +are generic. + +This will cause an error: + +``` +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(T, T, T); +``` + +This will not: + +``` +#![feature(repr_simd)] + +#[repr(simd)] +struct Good(u32, u32, u32); +``` diff --git a/src/librustc_error_codes/error_codes/E0075.md b/src/librustc_error_codes/error_codes/E0075.md new file mode 100644 index 0000000000..969c1ee713 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0075.md @@ -0,0 +1,23 @@ +A `#[simd]` attribute was applied to an empty tuple struct. + +Erroneous code example: + +```compile_fail,E0075 +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad; // error! +``` + +The `#[simd]` attribute can only be applied to non empty tuple structs, because +it doesn't make sense to try to use SIMD operations when there are no values to +operate on. + +Fixed example: + +``` +#![feature(repr_simd)] + +#[repr(simd)] +struct Good(u32); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0076.md b/src/librustc_error_codes/error_codes/E0076.md new file mode 100644 index 0000000000..f293a2a577 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0076.md @@ -0,0 +1,24 @@ +All types in a tuple struct aren't the same when using the `#[simd]` +attribute. + +Erroneous code example: + +```compile_fail,E0076 +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(u16, u32, u32); // error! +``` + +When using the `#[simd]` attribute to automatically use SIMD operations in tuple +struct, the types in the struct must all be of the same type, or the compiler +will trigger this error. + +Fixed example: + +``` +#![feature(repr_simd)] + +#[repr(simd)] +struct Good(u32, u32, u32); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0077.md b/src/librustc_error_codes/error_codes/E0077.md new file mode 100644 index 0000000000..b14513c6cc --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0077.md @@ -0,0 +1,23 @@ +A tuple struct's element isn't a machine type when using the `#[simd]` +attribute. + +Erroneous code example: + +```compile_fail,E0077 +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(String); // error! +``` + +When using the `#[simd]` attribute on a tuple struct, the elements in the tuple +must be machine types so SIMD operations can be applied to them. + +Fixed example: + +``` +#![feature(repr_simd)] + +#[repr(simd)] +struct Good(u32, u32, u32); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0080.md b/src/librustc_error_codes/error_codes/E0080.md new file mode 100644 index 0000000000..273238a943 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0080.md @@ -0,0 +1,20 @@ +A constant value failed to get evaluated. + +Erroneous code example: + +```compile_fail,E0080 +enum Enum { + X = (1 << 500), + Y = (1 / 0), +} +``` + +This error indicates that the compiler was unable to sensibly evaluate a +constant expression that had to be evaluated. Attempting to divide by 0 +or causing an integer overflow are two ways to induce this error. + +Ensure that the expressions given can be evaluated as the desired integer type. +See the FFI section of the Reference for more information about using a custom +integer type: + +https://doc.rust-lang.org/reference.html#ffi-attributes diff --git a/src/librustc_error_codes/error_codes/E0081.md b/src/librustc_error_codes/error_codes/E0081.md new file mode 100644 index 0000000000..fd5eca68e2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0081.md @@ -0,0 +1,37 @@ +A discrimant value is present more than once. + +Erroneous code example: + +```compile_fail,E0081 +enum Enum { + P = 3, + X = 3, // error! + Y = 5, +} +``` + +Enum discriminants are used to differentiate enum variants stored in memory. +This error indicates that the same value was used for two or more variants, +making it impossible to distinguish them. + +``` +enum Enum { + P, + X = 3, // ok! + Y = 5, +} +``` + +Note that variants without a manually specified discriminant are numbered from +top to bottom starting from 0, so clashes can occur with seemingly unrelated +variants. + +```compile_fail,E0081 +enum Bad { + X, + Y = 0, // error! +} +``` + +Here `X` will have already been specified the discriminant 0 by the time `Y` is +encountered, so a conflict occurs. diff --git a/src/librustc_error_codes/error_codes/E0084.md b/src/librustc_error_codes/error_codes/E0084.md new file mode 100644 index 0000000000..2388bc635d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0084.md @@ -0,0 +1,27 @@ +An unsupported representation was attempted on a zero-variant enum. + +Erroneous code example: + +```compile_fail,E0084 +#[repr(i32)] +enum NightsWatch {} // error: unsupported representation for zero-variant enum +``` + +It is impossible to define an integer type to be used to represent zero-variant +enum values because there are no zero-variant enum values. There is no way to +construct an instance of the following type using only safe code. So you have +two solutions. Either you add variants in your enum: + +``` +#[repr(i32)] +enum NightsWatch { + JonSnow, + Commander, +} +``` + +or you remove the integer represention of your enum: + +``` +enum NightsWatch {} +``` diff --git a/src/librustc_error_codes/error_codes/E0087.md b/src/librustc_error_codes/error_codes/E0087.md new file mode 100644 index 0000000000..9d292186f0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0087.md @@ -0,0 +1,15 @@ +#### Note: this error code is no longer emitted by the compiler. + +Too many type arguments were supplied for a function. For example: + +```compile_fail,E0107 +fn foo() {} + +fn main() { + foo::(); // error: wrong number of type arguments: + // expected 1, found 2 +} +``` + +The number of supplied arguments must exactly match the number of defined type +parameters. diff --git a/src/librustc_error_codes/error_codes/E0088.md b/src/librustc_error_codes/error_codes/E0088.md new file mode 100644 index 0000000000..7780ad5b56 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0088.md @@ -0,0 +1,45 @@ +#### Note: this error code is no longer emitted by the compiler. + +You gave too many lifetime arguments. Erroneous code example: + +```compile_fail,E0107 +fn f() {} + +fn main() { + f::<'static>() // error: wrong number of lifetime arguments: + // expected 0, found 1 +} +``` + +Please check you give the right number of lifetime arguments. Example: + +``` +fn f() {} + +fn main() { + f() // ok! +} +``` + +It's also important to note that the Rust compiler can generally +determine the lifetime by itself. Example: + +``` +struct Foo { + value: String +} + +impl Foo { + // it can be written like this + fn get_value<'a>(&'a self) -> &'a str { &self.value } + // but the compiler works fine with this too: + fn without_lifetime(&self) -> &str { &self.value } +} + +fn main() { + let f = Foo { value: "hello".to_owned() }; + + println!("{}", f.get_value()); + println!("{}", f.without_lifetime()); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0089.md b/src/librustc_error_codes/error_codes/E0089.md new file mode 100644 index 0000000000..504fbc7b96 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0089.md @@ -0,0 +1,25 @@ +#### Note: this error code is no longer emitted by the compiler. + +Too few type arguments were supplied for a function. For example: + +```compile_fail,E0107 +fn foo() {} + +fn main() { + foo::(); // error: wrong number of type arguments: expected 2, found 1 +} +``` + +Note that if a function takes multiple type arguments but you want the compiler +to infer some of them, you can use type placeholders: + +```compile_fail,E0107 +fn foo(x: T) {} + +fn main() { + let x: bool = true; + foo::(x); // error: wrong number of type arguments: + // expected 2, found 1 + foo::<_, f64>(x); // same as `foo::(x)` +} +``` diff --git a/src/librustc_error_codes/error_codes/E0090.md b/src/librustc_error_codes/error_codes/E0090.md new file mode 100644 index 0000000000..e091bb6c9f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0090.md @@ -0,0 +1,22 @@ +#### Note: this error code is no longer emitted by the compiler. + +You gave too few lifetime arguments. Example: + +```compile_fail,E0107 +fn foo<'a: 'b, 'b: 'a>() {} + +fn main() { + foo::<'static>(); // error: wrong number of lifetime arguments: + // expected 2, found 1 +} +``` + +Please check you give the right number of lifetime arguments. Example: + +``` +fn foo<'a: 'b, 'b: 'a>() {} + +fn main() { + foo::<'static, 'static>(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0091.md b/src/librustc_error_codes/error_codes/E0091.md new file mode 100644 index 0000000000..03cb328037 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0091.md @@ -0,0 +1,16 @@ +An unnecessary type or const parameter was given in a type alias. + +Erroneous code example: + +```compile_fail,E0091 +type Foo = u32; // error: type parameter `T` is unused +// or: +type Foo = Box; // error: type parameter `B` is unused +``` + +Please check you didn't write too many parameters. Example: + +``` +type Foo = u32; // ok! +type Foo2 = Box; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0092.md b/src/librustc_error_codes/error_codes/E0092.md new file mode 100644 index 0000000000..e289534bf7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0092.md @@ -0,0 +1,24 @@ +An undefined atomic operation function was declared. + +Erroneous code example: + +```compile_fail,E0092 +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn atomic_foo(); // error: unrecognized atomic operation + // function +} +``` + +Please check you didn't make a mistake in the function's name. All intrinsic +functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in +`libcore/intrinsics.rs` in the Rust source code. Example: + +``` +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn atomic_fence(); // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0093.md b/src/librustc_error_codes/error_codes/E0093.md new file mode 100644 index 0000000000..8e7de1a9d3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0093.md @@ -0,0 +1,35 @@ +An unknown intrinsic function was declared. + +Erroneous code example: + +```compile_fail,E0093 +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn foo(); // error: unrecognized intrinsic function: `foo` +} + +fn main() { + unsafe { + foo(); + } +} +``` + +Please check you didn't make a mistake in the function's name. All intrinsic +functions are defined in `librustc_codegen_llvm/intrinsic.rs` and in +`libcore/intrinsics.rs` in the Rust source code. Example: + +``` +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn atomic_fence(); // ok! +} + +fn main() { + unsafe { + atomic_fence(); + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0094.md b/src/librustc_error_codes/error_codes/E0094.md new file mode 100644 index 0000000000..42baa65bf9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0094.md @@ -0,0 +1,24 @@ +An invalid number of type parameters was given to an intrinsic function. + +Erroneous code example: + +```compile_fail,E0094 +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn size_of() -> usize; // error: intrinsic has wrong number + // of type parameters +} +``` + +Please check that you provided the right number of type parameters +and verify with the function declaration in the Rust source code. +Example: + +``` +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn size_of() -> usize; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0106.md b/src/librustc_error_codes/error_codes/E0106.md new file mode 100644 index 0000000000..60ca1ddc28 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0106.md @@ -0,0 +1,53 @@ +This error indicates that a lifetime is missing from a type. If it is an error +inside a function signature, the problem may be with failing to adhere to the +lifetime elision rules (see below). + +Erroneous code examples: + +```compile_fail,E0106 +struct Foo1 { x: &bool } + // ^ expected lifetime parameter +struct Foo2<'a> { x: &'a bool } // correct + +struct Bar1 { x: Foo2 } + // ^^^^ expected lifetime parameter +struct Bar2<'a> { x: Foo2<'a> } // correct + +enum Baz1 { A(u8), B(&bool), } + // ^ expected lifetime parameter +enum Baz2<'a> { A(u8), B(&'a bool), } // correct + +type MyStr1 = &str; + // ^ expected lifetime parameter +type MyStr2<'a> = &'a str; // correct +``` + +Lifetime elision is a special, limited kind of inference for lifetimes in +function signatures which allows you to leave out lifetimes in certain cases. +For more background on lifetime elision see [the book][book-le]. + +The lifetime elision rules require that any function signature with an elided +output lifetime must either have: + + - exactly one input lifetime + - or, multiple input lifetimes, but the function must also be a method with a + `&self` or `&mut self` receiver + +In the first case, the output lifetime is inferred to be the same as the unique +input lifetime. In the second case, the lifetime is instead inferred to be the +same as the lifetime on `&self` or `&mut self`. + +Here are some examples of elision errors: + +```compile_fail,E0106 +// error, no input lifetimes +fn foo() -> &str { } + +// error, `x` and `y` have distinct lifetimes inferred +fn bar(x: &str, y: &str) -> &str { } + +// error, `y`'s lifetime is inferred to be distinct from `x`'s +fn baz<'a>(x: &'a str, y: &str) -> &str { } +``` + +[book-le]: https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision diff --git a/src/librustc_error_codes/error_codes/E0107.md b/src/librustc_error_codes/error_codes/E0107.md new file mode 100644 index 0000000000..4d22b17fe1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0107.md @@ -0,0 +1,44 @@ +An incorrect number of generic arguments were provided. + +Erroneous code example: + +```compile_fail,E0107 +struct Foo { x: T } + +struct Bar { x: Foo } // error: wrong number of type arguments: + // expected 1, found 0 +struct Baz { x: Foo } // error: wrong number of type arguments: + // expected 1, found 2 + +fn foo(x: T, y: U) {} +fn f() {} + +fn main() { + let x: bool = true; + foo::(x); // error: wrong number of type arguments: + // expected 2, found 1 + foo::(x, 2, 4); // error: wrong number of type arguments: + // expected 2, found 3 + f::<'static>(); // error: wrong number of lifetime arguments + // expected 0, found 1 +} +``` + +When using/declaring an item with generic arguments, you must provide the exact +same number: + +``` +struct Foo { x: T } + +struct Bar { x: Foo } // ok! +struct Baz { x: Foo, y: Foo } // ok! + +fn foo(x: T, y: U) {} +fn f() {} + +fn main() { + let x: bool = true; + foo::(x, 12); // ok! + f(); // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0109.md b/src/librustc_error_codes/error_codes/E0109.md new file mode 100644 index 0000000000..2eab9725a6 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0109.md @@ -0,0 +1,22 @@ +You tried to provide a generic argument to a type which doesn't need it. + +Erroneous code example: + +```compile_fail,E0109 +type X = u32; // error: type arguments are not allowed for this type +type Y = bool<'static>; // error: lifetime parameters are not allowed on + // this type +``` + +Check that you used the correct argument and that the definition is correct. + +Example: + +``` +type X = u32; // ok! +type Y = bool; // ok! +``` + +Note that generic arguments for enum variant constructors go after the variant, +not after the enum. For example, you would write `Option::None::`, +rather than `Option::::None`. diff --git a/src/librustc_error_codes/error_codes/E0110.md b/src/librustc_error_codes/error_codes/E0110.md new file mode 100644 index 0000000000..b9fe406ffb --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0110.md @@ -0,0 +1,4 @@ +#### Note: this error code is no longer emitted by the compiler. + +You tried to provide a lifetime to a type which doesn't need it. +See `E0109` for more details. diff --git a/src/librustc_error_codes/error_codes/E0116.md b/src/librustc_error_codes/error_codes/E0116.md new file mode 100644 index 0000000000..ca849c2a12 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0116.md @@ -0,0 +1,27 @@ +An inherent implementation was defined for a type outside the current crate. + +Erroneous code example: + +```compile_fail,E0116 +impl Vec { } // error +``` + +You can only define an inherent implementation for a type in the same crate +where the type was defined. For example, an `impl` block as above is not allowed +since `Vec` is defined in the standard library. + +To fix this problem, you can do either of these things: + + - define a trait that has the desired associated functions/types/constants and + implement the trait for the type in question + - define a new type wrapping the type and define an implementation on the new + type + +Note that using the `type` keyword does not work here because `type` only +introduces a type alias: + +```compile_fail,E0116 +type Bytes = Vec; + +impl Bytes { } // error, same as above +``` diff --git a/src/librustc_error_codes/error_codes/E0117.md b/src/librustc_error_codes/error_codes/E0117.md new file mode 100644 index 0000000000..7fa211d4a2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0117.md @@ -0,0 +1,50 @@ +The `Drop` trait was implemented on a non-struct type. + +Erroneous code example: + +```compile_fail,E0117 +impl Drop for u32 {} +``` + +This error indicates a violation of one of Rust's orphan rules for trait +implementations. The rule prohibits any implementation of a foreign trait (a +trait defined in another crate) where + + - the type that is implementing the trait is foreign + - all of the parameters being passed to the trait (if there are any) are also + foreign. + +To avoid this kind of error, ensure that at least one local type is referenced +by the `impl`: + +``` +pub struct Foo; // you define your type in your crate + +impl Drop for Foo { // and you can implement the trait on it! + // code of trait implementation here +# fn drop(&mut self) { } +} + +impl From for i32 { // or you use a type from your crate as + // a type parameter + fn from(i: Foo) -> i32 { + 0 + } +} +``` + +Alternatively, define a trait locally and implement that instead: + +``` +trait Bar { + fn get(&self) -> usize; +} + +impl Bar for u32 { + fn get(&self) -> usize { 0 } +} +``` + +For information on the design of the orphan rules, see [RFC 1023]. + +[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md diff --git a/src/librustc_error_codes/error_codes/E0118.md b/src/librustc_error_codes/error_codes/E0118.md new file mode 100644 index 0000000000..5cb5f506e0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0118.md @@ -0,0 +1,43 @@ +An inherent implementation was defined for something which isn't a struct nor +an enum. + +Erroneous code example: + +```compile_fail,E0118 +impl (u8, u8) { // error: no base type found for inherent implementation + fn get_state(&self) -> String { + // ... + } +} +``` + +To fix this error, please implement a trait on the type or wrap it in a struct. +Example: + +``` +// we create a trait here +trait LiveLongAndProsper { + fn get_state(&self) -> String; +} + +// and now you can implement it on (u8, u8) +impl LiveLongAndProsper for (u8, u8) { + fn get_state(&self) -> String { + "He's dead, Jim!".to_owned() + } +} +``` + +Alternatively, you can create a newtype. A newtype is a wrapping tuple-struct. +For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`. +Example: + +``` +struct TypeWrapper((u8, u8)); + +impl TypeWrapper { + fn get_state(&self) -> String { + "Fascinating!".to_owned() + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0119.md b/src/librustc_error_codes/error_codes/E0119.md new file mode 100644 index 0000000000..e596349e5e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0119.md @@ -0,0 +1,59 @@ +There are conflicting trait implementations for the same type. + +Erroneous code example: + +```compile_fail,E0119 +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +struct Foo { + value: usize +} + +impl MyTrait for Foo { // error: conflicting implementations of trait + // `MyTrait` for type `Foo` + fn get(&self) -> usize { self.value } +} +``` + +When looking for the implementation for the trait, the compiler finds +both the `impl MyTrait for T` where T is all types and the `impl +MyTrait for Foo`. Since a trait cannot be implemented multiple times, +this is an error. So, when you write: + +``` +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} +``` + +This makes the trait implemented on all types in the scope. So if you +try to implement it on another one after that, the implementations will +conflict. Example: + +``` +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +struct Foo; + +fn main() { + let f = Foo; + + f.get(); // the trait is implemented so we can use it +} +``` diff --git a/src/librustc_error_codes/error_codes/E0120.md b/src/librustc_error_codes/error_codes/E0120.md new file mode 100644 index 0000000000..99c2a493a4 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0120.md @@ -0,0 +1,36 @@ +An attempt was made to implement Drop on a trait, which is not allowed: only +structs and enums can implement Drop. An example causing this error: + +```compile_fail,E0120 +trait MyTrait {} + +impl Drop for MyTrait { + fn drop(&mut self) {} +} +``` + +A workaround for this problem is to wrap the trait up in a struct, and implement +Drop on that. An example is shown below: + +``` +trait MyTrait {} +struct MyWrapper { foo: T } + +impl Drop for MyWrapper { + fn drop(&mut self) {} +} + +``` + +Alternatively, wrapping trait objects requires something like the following: + +``` +trait MyTrait {} + +//or Box, if you wanted an owned trait object +struct MyWrapper<'a> { foo: &'a MyTrait } + +impl <'a> Drop for MyWrapper<'a> { + fn drop(&mut self) {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0121.md b/src/librustc_error_codes/error_codes/E0121.md new file mode 100644 index 0000000000..069d0fc48f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0121.md @@ -0,0 +1,10 @@ +In order to be consistent with Rust's lack of global type inference, +type and const placeholders are disallowed by design in item signatures. + +Examples of this error include: + +```compile_fail,E0121 +fn foo() -> _ { 5 } // error, explicitly write out the return type instead + +static BAR: _ = "test"; // error, explicitly write out the type instead +``` diff --git a/src/librustc_error_codes/error_codes/E0124.md b/src/librustc_error_codes/error_codes/E0124.md new file mode 100644 index 0000000000..a7836526a7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0124.md @@ -0,0 +1,18 @@ +You declared two fields of a struct with the same name. Erroneous code +example: + +```compile_fail,E0124 +struct Foo { + field1: i32, + field1: i32, // error: field is already declared +} +``` + +Please verify that the field names have been correctly spelled. Example: + +``` +struct Foo { + field1: i32, + field2: i32, // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0128.md b/src/librustc_error_codes/error_codes/E0128.md new file mode 100644 index 0000000000..d0a4b32f96 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0128.md @@ -0,0 +1,24 @@ +Type parameter defaults can only use parameters that occur before them. +Erroneous code example: + +```compile_fail,E0128 +struct Foo { + field1: T, + field2: U, +} +// error: type parameters with a default cannot use forward declared +// identifiers +``` + +Since type parameters are evaluated in-order, you may be able to fix this issue +by doing: + +``` +struct Foo { + field1: T, + field2: U, +} +``` + +Please also verify that this wasn't because of a name-clash and rename the type +parameter if so. diff --git a/src/librustc_error_codes/error_codes/E0130.md b/src/librustc_error_codes/error_codes/E0130.md new file mode 100644 index 0000000000..5273f3ad14 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0130.md @@ -0,0 +1,31 @@ +You declared a pattern as an argument in a foreign function declaration. + +Erroneous code example: + +```compile_fail +extern { + fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign + // function declarations +} +``` + +Please replace the pattern argument with a regular one. Example: + +``` +struct SomeStruct { + a: u32, + b: u32, +} + +extern { + fn foo(s: SomeStruct); // ok! +} +``` + +Or: + +``` +extern { + fn foo(a: (u32, u32)); // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0131.md b/src/librustc_error_codes/error_codes/E0131.md new file mode 100644 index 0000000000..a70a02925b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0131.md @@ -0,0 +1,8 @@ +It is not possible to define `main` with generic parameters. +When `main` is present, it must take no arguments and return `()`. +Erroneous code example: + +```compile_fail,E0131 +fn main() { // error: main function is not allowed to have generic parameters +} +``` diff --git a/src/librustc_error_codes/error_codes/E0132.md b/src/librustc_error_codes/error_codes/E0132.md new file mode 100644 index 0000000000..a23cc988bd --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0132.md @@ -0,0 +1,32 @@ +A function with the `start` attribute was declared with type parameters. + +Erroneous code example: + +```compile_fail,E0132 +#![feature(start)] + +#[start] +fn f() {} +``` + +It is not possible to declare type parameters on a function that has the `start` +attribute. Such a function must have the following type signature (for more +information, view [the unstable book][1]): + +[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib + +``` +# let _: +fn(isize, *const *const u8) -> isize; +``` + +Example: + +``` +#![feature(start)] + +#[start] +fn my_start(argc: isize, argv: *const *const u8) -> isize { + 0 +} +``` diff --git a/src/librustc_error_codes/error_codes/E0133.md b/src/librustc_error_codes/error_codes/E0133.md new file mode 100644 index 0000000000..0488cdd808 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0133.md @@ -0,0 +1,31 @@ +Unsafe code was used outside of an unsafe function or block. + +Erroneous code example: + +```compile_fail,E0133 +unsafe fn f() { return; } // This is the unsafe code + +fn main() { + f(); // error: call to unsafe function requires unsafe function or block +} +``` + +Using unsafe functionality is potentially dangerous and disallowed by safety +checks. Examples: + +* Dereferencing raw pointers +* Calling functions via FFI +* Calling functions marked unsafe + +These safety checks can be relaxed for a section of the code by wrapping the +unsafe instructions with an `unsafe` block. For instance: + +``` +unsafe fn f() { return; } + +fn main() { + unsafe { f(); } // ok! +} +``` + +See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html diff --git a/src/librustc_error_codes/error_codes/E0136.md b/src/librustc_error_codes/error_codes/E0136.md new file mode 100644 index 0000000000..c0e8c7e061 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0136.md @@ -0,0 +1,16 @@ +A binary can only have one entry point, and by default that entry point is the +function `main()`. If there are multiple such functions, please rename one. + +Erroneous code example: + +```compile_fail,E0136 +fn main() { + // ... +} + +// ... + +fn main() { // error! + // ... +} +``` diff --git a/src/librustc_error_codes/error_codes/E0137.md b/src/librustc_error_codes/error_codes/E0137.md new file mode 100644 index 0000000000..0a02913d23 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0137.md @@ -0,0 +1,24 @@ +More than one function was declared with the `#[main]` attribute. + +Erroneous code example: + +```compile_fail,E0137 +#![feature(main)] + +#[main] +fn foo() {} + +#[main] +fn f() {} // error: multiple functions with a `#[main]` attribute +``` + +This error indicates that the compiler found multiple functions with the +`#[main]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(main)] + +#[main] +fn f() {} // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0138.md b/src/librustc_error_codes/error_codes/E0138.md new file mode 100644 index 0000000000..3f5eaea9f9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0138.md @@ -0,0 +1,25 @@ +More than one function was declared with the `#[start]` attribute. + +Erroneous code example: + +```compile_fail,E0138 +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize {} + +#[start] +fn f(argc: isize, argv: *const *const u8) -> isize {} +// error: multiple 'start' functions +``` + +This error indicates that the compiler found multiple functions with the +`#[start]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0139.md b/src/librustc_error_codes/error_codes/E0139.md new file mode 100644 index 0000000000..a116cf2939 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0139.md @@ -0,0 +1,84 @@ +#### Note: this error code is no longer emitted by the compiler. + +There are various restrictions on transmuting between types in Rust; for example +types being transmuted must have the same size. To apply all these restrictions, +the compiler must know the exact types that may be transmuted. When type +parameters are involved, this cannot always be done. + +So, for example, the following is not allowed: + +``` +use std::mem::transmute; + +struct Foo(Vec); + +fn foo(x: Vec) { + // we are transmuting between Vec and Foo here + let y: Foo = unsafe { transmute(x) }; + // do something with y +} +``` + +In this specific case there's a good chance that the transmute is harmless (but +this is not guaranteed by Rust). However, when alignment and enum optimizations +come into the picture, it's quite likely that the sizes may or may not match +with different type parameter substitutions. It's not possible to check this for +_all_ possible types, so `transmute()` simply only accepts types without any +unsubstituted type parameters. + +If you need this, there's a good chance you're doing something wrong. Keep in +mind that Rust doesn't guarantee much about the layout of different structs +(even two structs with identical declarations may have different layouts). If +there is a solution that avoids the transmute entirely, try it instead. + +If it's possible, hand-monomorphize the code by writing the function for each +possible type substitution. It's possible to use traits to do this cleanly, +for example: + +``` +use std::mem::transmute; + +struct Foo(Vec); + +trait MyTransmutableType: Sized { + fn transmute(_: Vec) -> Foo; +} + +impl MyTransmutableType for u8 { + fn transmute(x: Vec) -> Foo { + unsafe { transmute(x) } + } +} + +impl MyTransmutableType for String { + fn transmute(x: Vec) -> Foo { + unsafe { transmute(x) } + } +} + +// ... more impls for the types you intend to transmute + +fn foo(x: Vec) { + let y: Foo = ::transmute(x); + // do something with y +} +``` + +Each impl will be checked for a size match in the transmute as usual, and since +there are no unbound type parameters involved, this should compile unless there +is a size mismatch in one of the impls. + +It is also possible to manually transmute: + +``` +# use std::ptr; +# let v = Some("value"); +# type SomeType = &'static [u8]; +unsafe { + ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType` +} +# ; +``` + +Note that this does not move `v` (unlike `transmute`), and may need a +call to `mem::forget(v)` in case you want to avoid destructors being called. diff --git a/src/librustc_error_codes/error_codes/E0152.md b/src/librustc_error_codes/error_codes/E0152.md new file mode 100644 index 0000000000..602dcb6e2c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0152.md @@ -0,0 +1,25 @@ +A lang item was redefined. + +Erroneous code example: + +```compile_fail,E0152 +#![feature(lang_items)] + +#[lang = "arc"] +struct Foo; // error: duplicate lang item found: `arc` +``` + +Lang items are already implemented in the standard library. Unless you are +writing a free-standing application (e.g., a kernel), you do not need to provide +them yourself. + +You can build a free-standing crate by adding `#![no_std]` to the crate +attributes: + +```ignore (only-for-syntax-highlight) +#![no_std] +``` + +See also the [unstable book][1]. + +[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib diff --git a/src/librustc_error_codes/error_codes/E0154.md b/src/librustc_error_codes/error_codes/E0154.md new file mode 100644 index 0000000000..725a775e72 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0154.md @@ -0,0 +1,33 @@ +#### Note: this error code is no longer emitted by the compiler. + +Imports (`use` statements) are not allowed after non-item statements, such as +variable declarations and expression statements. + +Here is an example that demonstrates the error: + +``` +fn f() { + // Variable declaration before import + let x = 0; + use std::io::Read; + // ... +} +``` + +The solution is to declare the imports at the top of the block, function, or +file. + +Here is the previous example again, with the correct order: + +``` +fn f() { + use std::io::Read; + let x = 0; + // ... +} +``` + +See the Declaration Statements section of the reference for more information +about what constitutes an Item declaration and what does not: + +https://doc.rust-lang.org/reference.html#statements diff --git a/src/librustc_error_codes/error_codes/E0158.md b/src/librustc_error_codes/error_codes/E0158.md new file mode 100644 index 0000000000..0a9ef9c393 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0158.md @@ -0,0 +1,38 @@ +An associated const has been referenced in a pattern. + +Erroneous code example: + +```compile_fail,E0158 +enum EFoo { A, B, C, D } + +trait Foo { + const X: EFoo; +} + +fn test(arg: EFoo) { + match arg { + A::X => { // error! + println!("A::X"); + } + } +} +``` + +`const` and `static` mean different things. A `const` is a compile-time +constant, an alias for a literal value. This property means you can match it +directly within a pattern. + +The `static` keyword, on the other hand, guarantees a fixed location in memory. +This does not always mean that the value is constant. For example, a global +mutex can be declared `static` as well. + +If you want to match against a `static`, consider using a guard instead: + +``` +static FORTY_TWO: i32 = 42; + +match Some(42) { + Some(x) if x == FORTY_TWO => {} + _ => {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0161.md b/src/librustc_error_codes/error_codes/E0161.md new file mode 100644 index 0000000000..26269db232 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0161.md @@ -0,0 +1,30 @@ +A value was moved. However, its size was not known at compile time, and only +values of a known size can be moved. + +Erroneous code example: + +```compile_fail,E0161 +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<[isize]> = box *array; + // error: cannot move a value of type [isize]: the size of [isize] cannot + // be statically determined +} +``` + +In Rust, you can only move a value when its size is known at compile time. + +To work around this restriction, consider "hiding" the value behind a reference: +either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move +it around as usual. Example: + +``` +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<&[isize]> = box array; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0162.md b/src/librustc_error_codes/error_codes/E0162.md new file mode 100644 index 0000000000..98146147f3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0162.md @@ -0,0 +1,26 @@ +#### Note: this error code is no longer emitted by the compiler. + +An if-let pattern attempts to match the pattern, and enters the body if the +match was successful. If the match is irrefutable (when it cannot fail to +match), use a regular `let`-binding instead. For instance: + +``` +struct Irrefutable(i32); +let irr = Irrefutable(0); + +// This fails to compile because the match is irrefutable. +if let Irrefutable(x) = irr { + // This body will always be executed. + // ... +} +``` + +Try this instead: + +``` +struct Irrefutable(i32); +let irr = Irrefutable(0); + +let Irrefutable(x) = irr; +println!("{}", x); +``` diff --git a/src/librustc_error_codes/error_codes/E0164.md b/src/librustc_error_codes/error_codes/E0164.md new file mode 100644 index 0000000000..b41ce6fad8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0164.md @@ -0,0 +1,24 @@ +This error means that an attempt was made to match a struct type enum +variant as a non-struct type: + +```compile_fail,E0164 +enum Foo { B { i: u32 } } + +fn bar(foo: Foo) -> u32 { + match foo { + Foo::B(i) => i, // error E0164 + } +} +``` + +Try using `{}` instead: + +``` +enum Foo { B { i: u32 } } + +fn bar(foo: Foo) -> u32 { + match foo { + Foo::B{i} => i, + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0165.md b/src/librustc_error_codes/error_codes/E0165.md new file mode 100644 index 0000000000..92243db455 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0165.md @@ -0,0 +1,27 @@ +#### Note: this error code is no longer emitted by the compiler. + +A while-let pattern attempts to match the pattern, and enters the body if the +match was successful. If the match is irrefutable (when it cannot fail to +match), use a regular `let`-binding inside a `loop` instead. For instance: + +```no_run +struct Irrefutable(i32); +let irr = Irrefutable(0); + +// This fails to compile because the match is irrefutable. +while let Irrefutable(x) = irr { + // ... +} +``` + +Try this instead: + +```no_run +struct Irrefutable(i32); +let irr = Irrefutable(0); + +loop { + let Irrefutable(x) = irr; + // ... +} +``` diff --git a/src/librustc_error_codes/error_codes/E0170.md b/src/librustc_error_codes/error_codes/E0170.md new file mode 100644 index 0000000000..4b870dbf22 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0170.md @@ -0,0 +1,46 @@ +Enum variants are qualified by default. For example, given this type: + +``` +enum Method { + GET, + POST, +} +``` + +You would match it using: + +``` +enum Method { + GET, + POST, +} + +let m = Method::GET; + +match m { + Method::GET => {}, + Method::POST => {}, +} +``` + +If you don't qualify the names, the code will bind new variables named "GET" and +"POST" instead. This behavior is likely not what you want, so `rustc` warns when +that happens. + +Qualified names are good practice, and most code works well with them. But if +you prefer them unqualified, you can import the variants into scope: + +``` +use Method::*; +enum Method { GET, POST } +# fn main() {} +``` + +If you want others to be able to import variants from your module directly, use +`pub use`: + +``` +pub use Method::*; +pub enum Method { GET, POST } +# fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0178.md b/src/librustc_error_codes/error_codes/E0178.md new file mode 100644 index 0000000000..07980ad83f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0178.md @@ -0,0 +1,19 @@ +In types, the `+` type operator has low precedence, so it is often necessary +to use parentheses. + +For example: + +```compile_fail,E0178 +trait Foo {} + +struct Bar<'a> { + w: &'a Foo + Copy, // error, use &'a (Foo + Copy) + x: &'a Foo + 'a, // error, use &'a (Foo + 'a) + y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a) + z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a) +} +``` + +More details can be found in [RFC 438]. + +[RFC 438]: https://github.com/rust-lang/rfcs/pull/438 diff --git a/src/librustc_error_codes/error_codes/E0184.md b/src/librustc_error_codes/error_codes/E0184.md new file mode 100644 index 0000000000..e7fa8dfd83 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0184.md @@ -0,0 +1,6 @@ +Explicitly implementing both Drop and Copy for a type is currently disallowed. +This feature can make some sense in theory, but the current implementation is +incorrect and can lead to memory unsafety (see [issue #20126][iss20126]), so +it has been disabled for now. + +[iss20126]: https://github.com/rust-lang/rust/issues/20126 diff --git a/src/librustc_error_codes/error_codes/E0185.md b/src/librustc_error_codes/error_codes/E0185.md new file mode 100644 index 0000000000..f0ad2af144 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0185.md @@ -0,0 +1,19 @@ +An associated function for a trait was defined to be static, but an +implementation of the trait declared the same function to be a method (i.e., to +take a `self` parameter). + +Here's an example of this error: + +```compile_fail,E0185 +trait Foo { + fn foo(); +} + +struct Bar; + +impl Foo for Bar { + // error, method `foo` has a `&self` declaration in the impl, but not in + // the trait + fn foo(&self) {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0186.md b/src/librustc_error_codes/error_codes/E0186.md new file mode 100644 index 0000000000..9135d5c1d5 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0186.md @@ -0,0 +1,19 @@ +An associated function for a trait was defined to be a method (i.e., to take a +`self` parameter), but an implementation of the trait declared the same function +to be static. + +Here's an example of this error: + +```compile_fail,E0186 +trait Foo { + fn foo(&self); +} + +struct Bar; + +impl Foo for Bar { + // error, method `foo` has a `&self` declaration in the trait, but not in + // the impl + fn foo() {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0191.md b/src/librustc_error_codes/error_codes/E0191.md new file mode 100644 index 0000000000..b79196f6ce --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0191.md @@ -0,0 +1,22 @@ +Trait objects need to have all associated types specified. Erroneous code +example: + +```compile_fail,E0191 +trait Trait { + type Bar; +} + +type Foo = Trait; // error: the value of the associated type `Bar` (from + // the trait `Trait`) must be specified +``` + +Please verify you specified all associated types of the trait and that you +used the right trait. Example: + +``` +trait Trait { + type Bar; +} + +type Foo = Trait; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0192.md b/src/librustc_error_codes/error_codes/E0192.md new file mode 100644 index 0000000000..33308868cb --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0192.md @@ -0,0 +1,4 @@ +Negative impls are only allowed for auto traits. For more +information see the [opt-in builtin traits RFC][RFC 19]. + +[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md diff --git a/src/librustc_error_codes/error_codes/E0193.md b/src/librustc_error_codes/error_codes/E0193.md new file mode 100644 index 0000000000..e29a949ffb --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0193.md @@ -0,0 +1,44 @@ +#### Note: this error code is no longer emitted by the compiler. + +`where` clauses must use generic type parameters: it does not make sense to use +them otherwise. An example causing this error: + +``` +trait Foo { + fn bar(&self); +} + +#[derive(Copy,Clone)] +struct Wrapper { + Wrapped: T +} + +impl Foo for Wrapper where Wrapper: Clone { + fn bar(&self) { } +} +``` + +This use of a `where` clause is strange - a more common usage would look +something like the following: + +``` +trait Foo { + fn bar(&self); +} + +#[derive(Copy,Clone)] +struct Wrapper { + Wrapped: T +} +impl Foo for Wrapper where Wrapper: Clone { + fn bar(&self) { } +} +``` + +Here, we're saying that the implementation exists on Wrapper only when the +wrapped type `T` implements `Clone`. The `where` clause is important because +some types will not implement `Clone`, and thus will not get this method. + +In our erroneous example, however, we're referencing a single concrete type. +Since we know for certain that `Wrapper` implements `Clone`, there's no +reason to also specify it in a `where` clause. diff --git a/src/librustc_error_codes/error_codes/E0195.md b/src/librustc_error_codes/error_codes/E0195.md new file mode 100644 index 0000000000..3606521020 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0195.md @@ -0,0 +1,34 @@ +Your method's lifetime parameters do not match the trait declaration. +Erroneous code example: + +```compile_fail,E0195 +trait Trait { + fn bar<'a,'b:'a>(x: &'a str, y: &'b str); +} + +struct Foo; + +impl Trait for Foo { + fn bar<'a,'b>(x: &'a str, y: &'b str) { + // error: lifetime parameters or bounds on method `bar` + // do not match the trait declaration + } +} +``` + +The lifetime constraint `'b` for bar() implementation does not match the +trait declaration. Ensure lifetime declarations match exactly in both trait +declaration and implementation. Example: + +``` +trait Trait { + fn t<'a,'b:'a>(x: &'a str, y: &'b str); +} + +struct Foo; + +impl Trait for Foo { + fn t<'a,'b:'a>(x: &'a str, y: &'b str) { // ok! + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0197.md b/src/librustc_error_codes/error_codes/E0197.md new file mode 100644 index 0000000000..0d91157e57 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0197.md @@ -0,0 +1,13 @@ +Inherent implementations (one that do not implement a trait but provide +methods associated with a type) are always safe because they are not +implementing an unsafe trait. Removing the `unsafe` keyword from the inherent +implementation will resolve this error. + +```compile_fail,E0197 +struct Foo; + +// this will cause this error +unsafe impl Foo { } +// converting it to this will fix it +impl Foo { } +``` diff --git a/src/librustc_error_codes/error_codes/E0198.md b/src/librustc_error_codes/error_codes/E0198.md new file mode 100644 index 0000000000..6504d60dbd --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0198.md @@ -0,0 +1,27 @@ +A negative implementation is one that excludes a type from implementing a +particular trait. Not being able to use a trait is always a safe operation, +so negative implementations are always safe and never need to be marked as +unsafe. + +```compile_fail +#![feature(optin_builtin_traits)] + +struct Foo; + +// unsafe is unnecessary +unsafe impl !Clone for Foo { } +``` + +This will compile: + +```ignore (ignore auto_trait future compatibility warning) +#![feature(optin_builtin_traits)] + +struct Foo; + +auto trait Enterprise {} + +impl !Enterprise for Foo { } +``` + +Please note that negative impls are only allowed for auto traits. diff --git a/src/librustc_error_codes/error_codes/E0199.md b/src/librustc_error_codes/error_codes/E0199.md new file mode 100644 index 0000000000..d0c12dc6f1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0199.md @@ -0,0 +1,14 @@ +Safe traits should not have unsafe implementations, therefore marking an +implementation for a safe trait unsafe will cause a compiler error. Removing +the unsafe marker on the trait noted in the error will resolve this problem. + +```compile_fail,E0199 +struct Foo; + +trait Bar { } + +// this won't compile because Bar is safe +unsafe impl Bar for Foo { } +// this will compile +impl Bar for Foo { } +``` diff --git a/src/librustc_error_codes/error_codes/E0200.md b/src/librustc_error_codes/error_codes/E0200.md new file mode 100644 index 0000000000..865e91430a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0200.md @@ -0,0 +1,14 @@ +Unsafe traits must have unsafe implementations. This error occurs when an +implementation for an unsafe trait isn't marked as unsafe. This may be resolved +by marking the unsafe implementation as unsafe. + +```compile_fail,E0200 +struct Foo; + +unsafe trait Bar { } + +// this won't compile because Bar is unsafe and impl isn't unsafe +impl Bar for Foo { } +// this will compile +unsafe impl Bar for Foo { } +``` diff --git a/src/librustc_error_codes/error_codes/E0201.md b/src/librustc_error_codes/error_codes/E0201.md new file mode 100644 index 0000000000..bdbf02f003 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0201.md @@ -0,0 +1,45 @@ +It is an error to define two associated items (like methods, associated types, +associated functions, etc.) with the same identifier. + +For example: + +```compile_fail,E0201 +struct Foo(u8); + +impl Foo { + fn bar(&self) -> bool { self.0 > 5 } + fn bar() {} // error: duplicate associated function +} + +trait Baz { + type Quux; + fn baz(&self) -> bool; +} + +impl Baz for Foo { + type Quux = u32; + + fn baz(&self) -> bool { true } + + // error: duplicate method + fn baz(&self) -> bool { self.0 > 5 } + + // error: duplicate associated type + type Quux = u32; +} +``` + +Note, however, that items with the same name are allowed for inherent `impl` +blocks that don't overlap: + +``` +struct Foo(T); + +impl Foo { + fn bar(&self) -> bool { self.0 > 5 } +} + +impl Foo { + fn bar(&self) -> bool { self.0 } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0202.md b/src/librustc_error_codes/error_codes/E0202.md new file mode 100644 index 0000000000..b20d338c5f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0202.md @@ -0,0 +1,5 @@ +Inherent associated types were part of [RFC 195] but are not yet implemented. +See [the tracking issue][iss8995] for the status of this implementation. + +[RFC 195]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md +[iss8995]: https://github.com/rust-lang/rust/issues/8995 diff --git a/src/librustc_error_codes/error_codes/E0203.md b/src/librustc_error_codes/error_codes/E0203.md new file mode 100644 index 0000000000..1edb519275 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0203.md @@ -0,0 +1,18 @@ +Having multiple relaxed default bounds is unsupported. + +Erroneous code example: + +```compile_fail,E0203 +struct Bad{ + inner: T +} +``` + +Here the type `T` cannot have a relaxed bound for multiple default traits +(`Sized` and `Send`). This can be fixed by only using one relaxed bound. + +``` +struct Good{ + inner: T +} +``` diff --git a/src/librustc_error_codes/error_codes/E0204.md b/src/librustc_error_codes/error_codes/E0204.md new file mode 100644 index 0000000000..3156901113 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0204.md @@ -0,0 +1,25 @@ +An attempt to implement the `Copy` trait for a struct failed because one of the +fields does not implement `Copy`. To fix this, you must implement `Copy` for the +mentioned field. Note that this may not be possible, as in the example of + +```compile_fail,E0204 +struct Foo { + foo : Vec, +} + +impl Copy for Foo { } +``` + +This fails because `Vec` does not implement `Copy` for any `T`. + +Here's another example that will fail: + +```compile_fail,E0204 +#[derive(Copy)] +struct Foo<'a> { + ty: &'a mut bool, +} +``` + +This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this +differs from the behavior for `&T`, which is always `Copy`). diff --git a/src/librustc_error_codes/error_codes/E0205.md b/src/librustc_error_codes/error_codes/E0205.md new file mode 100644 index 0000000000..7916f53ad3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0205.md @@ -0,0 +1,29 @@ +#### Note: this error code is no longer emitted by the compiler. + +An attempt to implement the `Copy` trait for an enum failed because one of the +variants does not implement `Copy`. To fix this, you must implement `Copy` for +the mentioned variant. Note that this may not be possible, as in the example of + +```compile_fail,E0204 +enum Foo { + Bar(Vec), + Baz, +} + +impl Copy for Foo { } +``` + +This fails because `Vec` does not implement `Copy` for any `T`. + +Here's another example that will fail: + +```compile_fail,E0204 +#[derive(Copy)] +enum Foo<'a> { + Bar(&'a mut bool), + Baz, +} +``` + +This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this +differs from the behavior for `&T`, which is always `Copy`). diff --git a/src/librustc_error_codes/error_codes/E0206.md b/src/librustc_error_codes/error_codes/E0206.md new file mode 100644 index 0000000000..fc4c0e07a1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0206.md @@ -0,0 +1,12 @@ +You can only implement `Copy` for a struct or enum. Both of the following +examples will fail, because neither `[u8; 256]` nor `&'static mut Bar` +(mutable reference to `Bar`) is a struct or enum: + +```compile_fail,E0206 +type Foo = [u8; 256]; +impl Copy for Foo { } // error + +#[derive(Copy, Clone)] +struct Bar; +impl Copy for &'static mut Bar { } // error +``` diff --git a/src/librustc_error_codes/error_codes/E0207.md b/src/librustc_error_codes/error_codes/E0207.md new file mode 100644 index 0000000000..67b2063504 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0207.md @@ -0,0 +1,131 @@ +Any type parameter or lifetime parameter of an `impl` must meet at least one of +the following criteria: + + - it appears in the _implementing type_ of the impl, e.g. `impl Foo` + - for a trait impl, it appears in the _implemented trait_, e.g. + `impl SomeTrait for Foo` + - it is bound as an associated type, e.g. `impl SomeTrait for T + where T: AnotherTrait` + +### Error example 1 + +Suppose we have a struct `Foo` and we would like to define some methods for it. +The following definition leads to a compiler error: + +```compile_fail,E0207 +struct Foo; + +impl Foo { +// error: the type parameter `T` is not constrained by the impl trait, self +// type, or predicates [E0207] + fn get(&self) -> T { + ::default() + } +} +``` + +The problem is that the parameter `T` does not appear in the implementing type +(`Foo`) of the impl. In this case, we can fix the error by moving the type +parameter from the `impl` to the method `get`: + + +``` +struct Foo; + +// Move the type parameter from the impl to the method +impl Foo { + fn get(&self) -> T { + ::default() + } +} +``` + +### Error example 2 + +As another example, suppose we have a `Maker` trait and want to establish a +type `FooMaker` that makes `Foo`s: + +```compile_fail,E0207 +trait Maker { + type Item; + fn make(&mut self) -> Self::Item; +} + +struct Foo { + foo: T +} + +struct FooMaker; + +impl Maker for FooMaker { +// error: the type parameter `T` is not constrained by the impl trait, self +// type, or predicates [E0207] + type Item = Foo; + + fn make(&mut self) -> Foo { + Foo { foo: ::default() } + } +} +``` + +This fails to compile because `T` does not appear in the trait or in the +implementing type. + +One way to work around this is to introduce a phantom type parameter into +`FooMaker`, like so: + +``` +use std::marker::PhantomData; + +trait Maker { + type Item; + fn make(&mut self) -> Self::Item; +} + +struct Foo { + foo: T +} + +// Add a type parameter to `FooMaker` +struct FooMaker { + phantom: PhantomData, +} + +impl Maker for FooMaker { + type Item = Foo; + + fn make(&mut self) -> Foo { + Foo { + foo: ::default(), + } + } +} +``` + +Another way is to do away with the associated type in `Maker` and use an input +type parameter instead: + +``` +// Use a type parameter instead of an associated type here +trait Maker { + fn make(&mut self) -> Item; +} + +struct Foo { + foo: T +} + +struct FooMaker; + +impl Maker> for FooMaker { + fn make(&mut self) -> Foo { + Foo { foo: ::default() } + } +} +``` + +### Additional information + +For more information, please see [RFC 447]. + +[RFC 447]: https://github.com/rust-lang/rfcs/blob/master/text/0447-no-unused-impl-parameters.md diff --git a/src/librustc_error_codes/error_codes/E0210.md b/src/librustc_error_codes/error_codes/E0210.md new file mode 100644 index 0000000000..dc2fd9b0ca --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0210.md @@ -0,0 +1,82 @@ +This error indicates a violation of one of Rust's orphan rules for trait +implementations. The rule concerns the use of type parameters in an +implementation of a foreign trait (a trait defined in another crate), and +states that type parameters must be "covered" by a local type. + +When implementing a foreign trait for a foreign type, +the trait must have one or more type parameters. +A type local to your crate must appear before any use of any type parameters. + +To understand what this means, it is perhaps easier to consider a few examples. + +If `ForeignTrait` is a trait defined in some external crate `foo`, then the +following trait `impl` is an error: + +```compile_fail,E0210 +# #[cfg(for_demonstration_only)] +extern crate foo; +# #[cfg(for_demonstration_only)] +use foo::ForeignTrait; +# use std::panic::UnwindSafe as ForeignTrait; + +impl ForeignTrait for T { } // error +# fn main() {} +``` + +To work around this, it can be covered with a local type, `MyType`: + +``` +# use std::panic::UnwindSafe as ForeignTrait; +struct MyType(T); +impl ForeignTrait for MyType { } // Ok +``` + +Please note that a type alias is not sufficient. + +For another example of an error, suppose there's another trait defined in `foo` +named `ForeignTrait2` that takes two type parameters. Then this `impl` results +in the same rule violation: + +```ignore (cannot-doctest-multicrate-project) +struct MyType2; +impl ForeignTrait2> for MyType2 { } // error +``` + +The reason for this is that there are two appearances of type parameter `T` in +the `impl` header, both as parameters for `ForeignTrait2`. The first appearance +is uncovered, and so runs afoul of the orphan rule. + +Consider one more example: + +```ignore (cannot-doctest-multicrate-project) +impl ForeignTrait2, T> for MyType2 { } // Ok +``` + +This only differs from the previous `impl` in that the parameters `T` and +`MyType` for `ForeignTrait2` have been swapped. This example does *not* +violate the orphan rule; it is permitted. + +To see why that last example was allowed, you need to understand the general +rule. Unfortunately this rule is a bit tricky to state. Consider an `impl`: + +```ignore (only-for-syntax-highlight) +impl ForeignTrait for T0 { ... } +``` + +where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn` +are types. One of the types `T0, ..., Tn` must be a local type (this is another +orphan rule, see the explanation for E0117). + +Both of the following must be true: +1. At least one of the types `T0..=Tn` must be a local type. +Let `Ti` be the first such type. +2. No uncovered type parameters `P1..=Pm` may appear in `T0..Ti` +(excluding `Ti`). + +For information on the design of the orphan rules, +see [RFC 2451] and [RFC 1023]. + +For information on the design of the orphan rules, see [RFC 1023]. + +[RFC 2451]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html +[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md diff --git a/src/librustc_error_codes/error_codes/E0211.md b/src/librustc_error_codes/error_codes/E0211.md new file mode 100644 index 0000000000..77289f0190 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0211.md @@ -0,0 +1,79 @@ +#### Note: this error code is no longer emitted by the compiler. + +You used a function or type which doesn't fit the requirements for where it was +used. Erroneous code examples: + +```compile_fail +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn size_of(); // error: intrinsic has wrong type +} + +// or: + +fn main() -> i32 { 0 } +// error: main function expects type: `fn() {main}`: expected (), found i32 + +// or: + +let x = 1u8; +match x { + 0u8..=3i8 => (), + // error: mismatched types in range: expected u8, found i8 + _ => () +} + +// or: + +use std::rc::Rc; +struct Foo; + +impl Foo { + fn x(self: Rc) {} + // error: mismatched self type: expected `Foo`: expected struct + // `Foo`, found struct `alloc::rc::Rc` +} +``` + +For the first code example, please check the function definition. Example: + +``` +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn size_of() -> usize; // ok! +} +``` + +The second case example is a bit particular: the main function must always +have this definition: + +```compile_fail +fn main(); +``` + +They never take parameters and never return types. + +For the third example, when you match, all patterns must have the same type +as the type you're matching on. Example: + +``` +let x = 1u8; + +match x { + 0u8..=3u8 => (), // ok! + _ => () +} +``` + +And finally, for the last example, only `Box`, `&Self`, `Self`, +or `&mut Self` work as explicit self parameters. Example: + +``` +struct Foo; + +impl Foo { + fn x(self: Box) {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0214.md b/src/librustc_error_codes/error_codes/E0214.md new file mode 100644 index 0000000000..f78c1c0cd0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0214.md @@ -0,0 +1,12 @@ +A generic type was described using parentheses rather than angle brackets. +For example: + +```compile_fail,E0214 +fn main() { + let v: Vec(&str) = vec!["foo"]; +} +``` + +This is not currently supported: `v` should be defined as `Vec<&str>`. +Parentheses are currently only used with generic types when defining parameters +for `Fn`-family traits. diff --git a/src/librustc_error_codes/error_codes/E0220.md b/src/librustc_error_codes/error_codes/E0220.md new file mode 100644 index 0000000000..43e075b522 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0220.md @@ -0,0 +1,41 @@ +You used an associated type which isn't defined in the trait. +Erroneous code example: + +```compile_fail,E0220 +trait T1 { + type Bar; +} + +type Foo = T1; // error: associated type `F` not found for `T1` + +// or: + +trait T2 { + type Bar; + + // error: Baz is used but not declared + fn return_bool(&self, _: &Self::Bar, _: &Self::Baz) -> bool; +} +``` + +Make sure that you have defined the associated type in the trait body. +Also, verify that you used the right trait or you didn't misspell the +associated type name. Example: + +``` +trait T1 { + type Bar; +} + +type Foo = T1; // ok! + +// or: + +trait T2 { + type Bar; + type Baz; // we declare `Baz` in our trait. + + // and now we can use it here: + fn return_bool(&self, _: &Self::Bar, _: &Self::Baz) -> bool; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0221.md b/src/librustc_error_codes/error_codes/E0221.md new file mode 100644 index 0000000000..53fabf490e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0221.md @@ -0,0 +1,43 @@ +An attempt was made to retrieve an associated type, but the type was ambiguous. +For example: + +```compile_fail,E0221 +trait T1 {} +trait T2 {} + +trait Foo { + type A: T1; +} + +trait Bar : Foo { + type A: T2; + fn do_something() { + let _: Self::A; + } +} +``` + +In this example, `Foo` defines an associated type `A`. `Bar` inherits that type +from `Foo`, and defines another associated type of the same name. As a result, +when we attempt to use `Self::A`, it's ambiguous whether we mean the `A` defined +by `Foo` or the one defined by `Bar`. + +There are two options to work around this issue. The first is simply to rename +one of the types. Alternatively, one can specify the intended type using the +following syntax: + +``` +trait T1 {} +trait T2 {} + +trait Foo { + type A: T1; +} + +trait Bar : Foo { + type A: T2; + fn do_something() { + let _: ::A; + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0223.md b/src/librustc_error_codes/error_codes/E0223.md new file mode 100644 index 0000000000..9fe0360425 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0223.md @@ -0,0 +1,32 @@ +An attempt was made to retrieve an associated type, but the type was ambiguous. +For example: + +```compile_fail,E0223 +trait MyTrait {type X; } + +fn main() { + let foo: MyTrait::X; +} +``` + +The problem here is that we're attempting to take the type of X from MyTrait. +Unfortunately, the type of X is not defined, because it's only made concrete in +implementations of the trait. A working version of this code might look like: + +``` +trait MyTrait {type X; } +struct MyStruct; + +impl MyTrait for MyStruct { + type X = u32; +} + +fn main() { + let foo: ::X; +} +``` + +This syntax specifies that we want the X type from MyTrait, as made concrete in +MyStruct. The reason that we cannot simply use `MyStruct::X` is that MyStruct +might implement two different traits with identically-named associated types. +This syntax allows disambiguation between the two. diff --git a/src/librustc_error_codes/error_codes/E0225.md b/src/librustc_error_codes/error_codes/E0225.md new file mode 100644 index 0000000000..b9820dc68e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0225.md @@ -0,0 +1,18 @@ +You attempted to use multiple types as bounds for a closure or trait object. +Rust does not currently support this. A simple example that causes this error: + +```compile_fail,E0225 +fn main() { + let _: Box; +} +``` + +Auto traits such as Send and Sync are an exception to this rule: +It's possible to have bounds of one non-builtin trait, plus any number of +auto traits. For example, the following compiles correctly: + +``` +fn main() { + let _: Box; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0229.md b/src/librustc_error_codes/error_codes/E0229.md new file mode 100644 index 0000000000..a8bd341a62 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0229.md @@ -0,0 +1,36 @@ +An associated type binding was done outside of the type parameter declaration +and `where` clause. Erroneous code example: + +```compile_fail,E0229 +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } +} + +fn baz(x: &>::A) {} +// error: associated type bindings are not allowed here +``` + +To solve this error, please move the type bindings in the type parameter +declaration: + +``` +# struct Bar; +# trait Foo { type A; } +fn baz>(x: &::A) {} // ok! +``` + +Or in the `where` clause: + +``` +# struct Bar; +# trait Foo { type A; } +fn baz(x: &::A) where I: Foo {} +``` diff --git a/src/librustc_error_codes/error_codes/E0230.md b/src/librustc_error_codes/error_codes/E0230.md new file mode 100644 index 0000000000..9dbcb8e010 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0230.md @@ -0,0 +1,29 @@ +The `#[rustc_on_unimplemented]` attribute lets you specify a custom error +message for when a particular trait isn't implemented on a type placed in a +position that needs that trait. For example, when the following code is +compiled: + +```compile_fail +#![feature(rustc_attrs)] + +fn foo>(x: T){} + +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +trait Index { /* ... */ } + +foo(true); // `bool` does not implement `Index` +``` + +There will be an error about `bool` not implementing `Index`, followed by a +note saying "the type `bool` cannot be indexed by `u8`". + +As you can see, you can specify type parameters in curly braces for +substitution with the actual types (using the regular format string syntax) in +a given situation. Furthermore, `{Self}` will substitute to the type (in this +case, `bool`) that we tried to use. + +This error appears when the curly braces contain an identifier which doesn't +match with any of the type parameters or the string `Self`. This might happen +if you misspelled a type parameter, or if you intended to use literal curly +braces. If it is the latter, escape the curly braces with a second curly brace +of the same type; e.g., a literal `{` is `{{`. diff --git a/src/librustc_error_codes/error_codes/E0231.md b/src/librustc_error_codes/error_codes/E0231.md new file mode 100644 index 0000000000..4f80da5454 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0231.md @@ -0,0 +1,27 @@ +The `#[rustc_on_unimplemented]` attribute lets you specify a custom error +message for when a particular trait isn't implemented on a type placed in a +position that needs that trait. For example, when the following code is +compiled: + +```compile_fail +#![feature(rustc_attrs)] + +fn foo>(x: T){} + +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +trait Index { /* ... */ } + +foo(true); // `bool` does not implement `Index` +``` + +there will be an error about `bool` not implementing `Index`, followed by a +note saying "the type `bool` cannot be indexed by `u8`". + +As you can see, you can specify type parameters in curly braces for +substitution with the actual types (using the regular format string syntax) in +a given situation. Furthermore, `{Self}` will substitute to the type (in this +case, `bool`) that we tried to use. + +This error appears when the curly braces do not contain an identifier. Please +add one of the same name as a type parameter. If you intended to use literal +braces, use `{{` and `}}` to escape them. diff --git a/src/librustc_error_codes/error_codes/E0232.md b/src/librustc_error_codes/error_codes/E0232.md new file mode 100644 index 0000000000..07a031488d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0232.md @@ -0,0 +1,22 @@ +The `#[rustc_on_unimplemented]` attribute lets you specify a custom error +message for when a particular trait isn't implemented on a type placed in a +position that needs that trait. For example, when the following code is +compiled: + +```compile_fail +#![feature(rustc_attrs)] + +fn foo>(x: T){} + +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +trait Index { /* ... */ } + +foo(true); // `bool` does not implement `Index` +``` + +there will be an error about `bool` not implementing `Index`, followed by a +note saying "the type `bool` cannot be indexed by `u8`". + +For this to work, some note must be specified. An empty attribute will not do +anything, please remove the attribute or add some helpful note for users of the +trait. diff --git a/src/librustc_error_codes/error_codes/E0243.md b/src/librustc_error_codes/error_codes/E0243.md new file mode 100644 index 0000000000..5d3d1828bf --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0243.md @@ -0,0 +1,13 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error indicates that not enough type parameters were found in a type or +trait. + +For example, the `Foo` struct below is defined to be generic in `T`, but the +type parameter is missing in the definition of `Bar`: + +```compile_fail,E0107 +struct Foo { x: T } + +struct Bar { x: Foo } +``` diff --git a/src/librustc_error_codes/error_codes/E0244.md b/src/librustc_error_codes/error_codes/E0244.md new file mode 100644 index 0000000000..5187b7b05d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0244.md @@ -0,0 +1,13 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error indicates that too many type parameters were found in a type or +trait. + +For example, the `Foo` struct below has no type parameters, but is supplied +with two in the definition of `Bar`: + +```compile_fail,E0107 +struct Foo { x: bool } + +struct Bar { x: Foo } +``` diff --git a/src/librustc_error_codes/error_codes/E0251.md b/src/librustc_error_codes/error_codes/E0251.md new file mode 100644 index 0000000000..4121dd2787 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0251.md @@ -0,0 +1,21 @@ +#### Note: this error code is no longer emitted by the compiler. + +Two items of the same name cannot be imported without rebinding one of the +items under a new local name. + +An example of this error: + +``` +use foo::baz; +use bar::*; // error, do `use foo::baz as quux` instead on the previous line + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0252.md b/src/librustc_error_codes/error_codes/E0252.md new file mode 100644 index 0000000000..e678944650 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0252.md @@ -0,0 +1,54 @@ +Two items of the same name cannot be imported without rebinding one of the +items under a new local name. + +Erroneous code example: + +```compile_fail,E0252 +use foo::baz; +use bar::baz; // error, do `use bar::baz as quux` instead + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` + +You can use aliases in order to fix this error. Example: + +``` +use foo::baz as foo_baz; +use bar::baz; // ok! + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` + +Or you can reference the item with its parent: + +``` +use bar::baz; + +fn main() { + let x = foo::baz; // ok! +} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0253.md b/src/librustc_error_codes/error_codes/E0253.md new file mode 100644 index 0000000000..aea51d4023 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0253.md @@ -0,0 +1,19 @@ +Attempt was made to import an unimportable value. This can happen when trying +to import a method from a trait. + +Erroneous code example: + +```compile_fail,E0253 +mod foo { + pub trait MyTrait { + fn do_something(); + } +} + +use foo::MyTrait::do_something; +// error: `do_something` is not directly importable + +fn main() {} +``` + +It's invalid to directly import methods belonging to a trait or concrete type. diff --git a/src/librustc_error_codes/error_codes/E0254.md b/src/librustc_error_codes/error_codes/E0254.md new file mode 100644 index 0000000000..44383ed6ea --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0254.md @@ -0,0 +1,36 @@ +Attempt was made to import an item whereas an extern crate with this name has +already been imported. + +Erroneous code example: + +```compile_fail,E0254 +extern crate core; + +mod foo { + pub trait core { + fn do_something(); + } +} + +use foo::core; // error: an extern crate named `core` has already + // been imported in this module + +fn main() {} +``` + +To fix this issue, you have to rename at least one of the two imports. +Example: + +``` +extern crate core as libcore; // ok! + +mod foo { + pub trait core { + fn do_something(); + } +} + +use foo::core; + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0255.md b/src/librustc_error_codes/error_codes/E0255.md new file mode 100644 index 0000000000..83f5ec3dda --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0255.md @@ -0,0 +1,44 @@ +You can't import a value whose name is the same as another value defined in the +module. + +Erroneous code example: + +```compile_fail,E0255 +use bar::foo; // error: an item named `foo` is already in scope + +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() {} +``` + +You can use aliases in order to fix this error. Example: + +``` +use bar::foo as bar_foo; // ok! + +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() {} +``` + +Or you can reference the item with its parent: + +``` +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() { + bar::foo(); // we get the item by referring to its parent +} +``` diff --git a/src/librustc_error_codes/error_codes/E0256.md b/src/librustc_error_codes/error_codes/E0256.md new file mode 100644 index 0000000000..385376cdad --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0256.md @@ -0,0 +1,18 @@ +#### Note: this error code is no longer emitted by the compiler. + +You can't import a type or module when the name of the item being imported is +the same as another type or submodule defined in the module. + +An example of this error: + +```compile_fail +use foo::Bar; // error + +type Bar = u32; + +mod foo { + pub mod Bar { } +} + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0259.md b/src/librustc_error_codes/error_codes/E0259.md new file mode 100644 index 0000000000..8d8f93db30 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0259.md @@ -0,0 +1,23 @@ +The name chosen for an external crate conflicts with another external crate +that has been imported into the current module. + +Erroneous code example: + +```compile_fail,E0259 +extern crate core; +extern crate std as core; + +fn main() {} +``` + +The solution is to choose a different name that doesn't conflict with any +external crate imported into the current module. + +Correct example: + +``` +extern crate core; +extern crate std as other_name; + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0260.md b/src/librustc_error_codes/error_codes/E0260.md new file mode 100644 index 0000000000..4a36735ae7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0260.md @@ -0,0 +1,34 @@ +The name for an item declaration conflicts with an external crate's name. + +Erroneous code example: + +```compile_fail,E0260 +extern crate core; + +struct core; + +fn main() {} +``` + +There are two possible solutions: + +Solution #1: Rename the item. + +``` +extern crate core; + +struct xyz; +``` + +Solution #2: Import the crate with a different name. + +``` +extern crate core as xyz; + +struct abc; +``` + +See the Declaration Statements section of the reference for more information +about what constitutes an Item declaration and what does not: + +https://doc.rust-lang.org/reference.html#statements diff --git a/src/librustc_error_codes/error_codes/E0261.md b/src/librustc_error_codes/error_codes/E0261.md new file mode 100644 index 0000000000..21cf8e7045 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0261.md @@ -0,0 +1,53 @@ +When using a lifetime like `'a` in a type, it must be declared before being +used. + +These two examples illustrate the problem: + +```compile_fail,E0261 +// error, use of undeclared lifetime name `'a` +fn foo(x: &'a str) { } + +struct Foo { + // error, use of undeclared lifetime name `'a` + x: &'a str, +} +``` + +These can be fixed by declaring lifetime parameters: + +``` +struct Foo<'a> { + x: &'a str, +} + +fn foo<'a>(x: &'a str) {} +``` + +Impl blocks declare lifetime parameters separately. You need to add lifetime +parameters to an impl block if you're implementing a type that has a lifetime +parameter of its own. +For example: + +```compile_fail,E0261 +struct Foo<'a> { + x: &'a str, +} + +// error, use of undeclared lifetime name `'a` +impl Foo<'a> { + fn foo<'a>(x: &'a str) {} +} +``` + +This is fixed by declaring the impl block like this: + +``` +struct Foo<'a> { + x: &'a str, +} + +// correct +impl<'a> Foo<'a> { + fn foo(x: &'a str) {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0262.md b/src/librustc_error_codes/error_codes/E0262.md new file mode 100644 index 0000000000..2dca6b1bb0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0262.md @@ -0,0 +1,8 @@ +Declaring certain lifetime names in parameters is disallowed. For example, +because the `'static` lifetime is a special built-in lifetime name denoting +the lifetime of the entire program, this is an error: + +```compile_fail,E0262 +// error, invalid lifetime parameter name `'static` +fn foo<'static>(x: &'static str) { } +``` diff --git a/src/librustc_error_codes/error_codes/E0263.md b/src/librustc_error_codes/error_codes/E0263.md new file mode 100644 index 0000000000..bb4da43b3f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0263.md @@ -0,0 +1,7 @@ +A lifetime name cannot be declared more than once in the same scope. For +example: + +```compile_fail,E0263 +// error, lifetime name `'a` declared twice in the same scope +fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { } +``` diff --git a/src/librustc_error_codes/error_codes/E0264.md b/src/librustc_error_codes/error_codes/E0264.md new file mode 100644 index 0000000000..e1e7516cec --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0264.md @@ -0,0 +1,22 @@ +An unknown external lang item was used. Erroneous code example: + +```compile_fail,E0264 +#![feature(lang_items)] + +extern "C" { + #[lang = "cake"] // error: unknown external lang item: `cake` + fn cake(); +} +``` + +A list of available external lang items is available in +`src/librustc/middle/weak_lang_items.rs`. Example: + +``` +#![feature(lang_items)] + +extern "C" { + #[lang = "panic_impl"] // ok! + fn cake(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0267.md b/src/librustc_error_codes/error_codes/E0267.md new file mode 100644 index 0000000000..066ebee0ff --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0267.md @@ -0,0 +1,20 @@ +This error indicates the use of a loop keyword (`break` or `continue`) inside a +closure but outside of any loop. Erroneous code example: + +```compile_fail,E0267 +let w = || { break; }; // error: `break` inside of a closure +``` + +`break` and `continue` keywords can be used as normal inside closures as long as +they are also contained within a loop. To halt the execution of a closure you +should instead use a return statement. Example: + +``` +let w = || { + for _ in 0..10 { + break; + } +}; + +w(); +``` diff --git a/src/librustc_error_codes/error_codes/E0268.md b/src/librustc_error_codes/error_codes/E0268.md new file mode 100644 index 0000000000..7f3ac11860 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0268.md @@ -0,0 +1,19 @@ +This error indicates the use of a loop keyword (`break` or `continue`) outside +of a loop. Without a loop to break out of or continue in, no sensible action can +be taken. Erroneous code example: + +```compile_fail,E0268 +fn some_func() { + break; // error: `break` outside of a loop +} +``` + +Please verify that you are using `break` and `continue` only in loops. Example: + +``` +fn some_func() { + for _ in 0..10 { + break; // ok! + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0271.md b/src/librustc_error_codes/error_codes/E0271.md new file mode 100644 index 0000000000..4078598b39 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0271.md @@ -0,0 +1,80 @@ +This is because of a type mismatch between the associated type of some +trait (e.g., `T::Bar`, where `T` implements `trait Quux { type Bar; }`) +and another type `U` that is required to be equal to `T::Bar`, but is not. +Examples follow. + +Here is a basic example: + +```compile_fail,E0271 +trait Trait { type AssociatedType; } + +fn foo(t: T) where T: Trait { + println!("in foo"); +} + +impl Trait for i8 { type AssociatedType = &'static str; } + +foo(3_i8); +``` + +Here is that same example again, with some explanatory comments: + +```compile_fail,E0271 +trait Trait { type AssociatedType; } + +fn foo(t: T) where T: Trait { +// ~~~~~~~~ ~~~~~~~~~~~~~~~~~~ +// | | +// This says `foo` can | +// only be used with | +// some type that | +// implements `Trait`. | +// | +// This says not only must +// `T` be an impl of `Trait` +// but also that the impl +// must assign the type `u32` +// to the associated type. + println!("in foo"); +} + +impl Trait for i8 { type AssociatedType = &'static str; } +//~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// | | +// `i8` does have | +// implementation | +// of `Trait`... | +// ... but it is an implementation +// that assigns `&'static str` to +// the associated type. + +foo(3_i8); +// Here, we invoke `foo` with an `i8`, which does not satisfy +// the constraint `::AssociatedType=u32`, and +// therefore the type-checker complains with this error code. +``` + +To avoid those issues, you have to make the types match correctly. +So we can fix the previous examples like this: + +``` +// Basic Example: +trait Trait { type AssociatedType; } + +fn foo(t: T) where T: Trait { + println!("in foo"); +} + +impl Trait for i8 { type AssociatedType = &'static str; } + +foo(3_i8); + +// For-Loop Example: +let vs = vec![1, 2, 3, 4]; +for v in &vs { + match v { + &1 => {} + _ => {} + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0275.md b/src/librustc_error_codes/error_codes/E0275.md new file mode 100644 index 0000000000..836a9a95fa --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0275.md @@ -0,0 +1,20 @@ +This error occurs when there was a recursive trait requirement that overflowed +before it could be evaluated. Often this means that there is unbounded +recursion in resolving some type bounds. + +For example, in the following code: + +```compile_fail,E0275 +trait Foo {} + +struct Bar(T); + +impl Foo for T where Bar: Foo {} +``` + +To determine if a `T` is `Foo`, we need to check if `Bar` is `Foo`. However, +to do this check, we need to determine that `Bar>` is `Foo`. To +determine this, we check if `Bar>>` is `Foo`, and so on. This is +clearly a recursive requirement that can't be resolved directly. + +Consider changing your trait bounds so that they're less self-referential. diff --git a/src/librustc_error_codes/error_codes/E0276.md b/src/librustc_error_codes/error_codes/E0276.md new file mode 100644 index 0000000000..0e3a613bf9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0276.md @@ -0,0 +1,19 @@ +This error occurs when a bound in an implementation of a trait does not match +the bounds specified in the original trait. For example: + +```compile_fail,E0276 +trait Foo { + fn foo(x: T); +} + +impl Foo for bool { + fn foo(x: T) where T: Copy {} +} +``` + +Here, all types implementing `Foo` must have a method `foo(x: T)` which can +take any type `T`. However, in the `impl` for `bool`, we have added an extra +bound that `T` is `Copy`, which isn't compatible with the original trait. + +Consider removing the bound from the method or adding the bound to the original +method definition in the trait. diff --git a/src/librustc_error_codes/error_codes/E0277.md b/src/librustc_error_codes/error_codes/E0277.md new file mode 100644 index 0000000000..2034a5b988 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0277.md @@ -0,0 +1,85 @@ +You tried to use a type which doesn't implement some trait in a place which +expected that trait. Erroneous code example: + +```compile_fail,E0277 +// here we declare the Foo trait with a bar method +trait Foo { + fn bar(&self); +} + +// we now declare a function which takes an object implementing the Foo trait +fn some_func(foo: T) { + foo.bar(); +} + +fn main() { + // we now call the method with the i32 type, which doesn't implement + // the Foo trait + some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied +} +``` + +In order to fix this error, verify that the type you're using does implement +the trait. Example: + +``` +trait Foo { + fn bar(&self); +} + +fn some_func(foo: T) { + foo.bar(); // we can now use this method since i32 implements the + // Foo trait +} + +// we implement the trait on the i32 type +impl Foo for i32 { + fn bar(&self) {} +} + +fn main() { + some_func(5i32); // ok! +} +``` + +Or in a generic context, an erroneous code example would look like: + +```compile_fail,E0277 +fn some_func(foo: T) { + println!("{:?}", foo); // error: the trait `core::fmt::Debug` is not + // implemented for the type `T` +} + +fn main() { + // We now call the method with the i32 type, + // which *does* implement the Debug trait. + some_func(5i32); +} +``` + +Note that the error here is in the definition of the generic function: Although +we only call it with a parameter that does implement `Debug`, the compiler +still rejects the function: It must work with all possible input types. In +order to make this example compile, we need to restrict the generic type we're +accepting: + +``` +use std::fmt; + +// Restrict the input type to types that implement Debug. +fn some_func(foo: T) { + println!("{:?}", foo); +} + +fn main() { + // Calling the method is still fine, as i32 implements Debug. + some_func(5i32); + + // This would fail to compile now: + // struct WithoutDebug; + // some_func(WithoutDebug); +} +``` + +Rust only looks at the signature of the called function, as such it must +already specify all requirements that will be used for every type parameter. diff --git a/src/librustc_error_codes/error_codes/E0281.md b/src/librustc_error_codes/error_codes/E0281.md new file mode 100644 index 0000000000..1a9796d279 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0281.md @@ -0,0 +1,20 @@ +#### Note: this error code is no longer emitted by the compiler. + +You tried to supply a type which doesn't implement some trait in a location +which expected that trait. This error typically occurs when working with +`Fn`-based types. Erroneous code example: + +```compile-fail +fn foo(x: F) { } + +fn main() { + // type mismatch: ... implements the trait `core::ops::Fn<(String,)>`, + // but the trait `core::ops::Fn<(usize,)>` is required + // [E0281] + foo(|y: String| { }); +} +``` + +The issue in this case is that `foo` is defined as accepting a `Fn` with one +argument of type `String`, but the closure we attempted to pass to it requires +one arguments of type `usize`. diff --git a/src/librustc_error_codes/error_codes/E0282.md b/src/librustc_error_codes/error_codes/E0282.md new file mode 100644 index 0000000000..54a9de0025 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0282.md @@ -0,0 +1,65 @@ +This error indicates that type inference did not result in one unique possible +type, and extra information is required. In most cases this can be provided +by adding a type annotation. Sometimes you need to specify a generic type +parameter manually. + +A common example is the `collect` method on `Iterator`. It has a generic type +parameter with a `FromIterator` bound, which for a `char` iterator is +implemented by `Vec` and `String` among others. Consider the following snippet +that reverses the characters of a string: + +```compile_fail,E0282 +let x = "hello".chars().rev().collect(); +``` + +In this case, the compiler cannot infer what the type of `x` should be: +`Vec` and `String` are both suitable candidates. To specify which type to +use, you can use a type annotation on `x`: + +``` +let x: Vec = "hello".chars().rev().collect(); +``` + +It is not necessary to annotate the full type. Once the ambiguity is resolved, +the compiler can infer the rest: + +``` +let x: Vec<_> = "hello".chars().rev().collect(); +``` + +Another way to provide the compiler with enough information, is to specify the +generic type parameter: + +``` +let x = "hello".chars().rev().collect::>(); +``` + +Again, you need not specify the full type if the compiler can infer it: + +``` +let x = "hello".chars().rev().collect::>(); +``` + +Apart from a method or function with a generic type parameter, this error can +occur when a type parameter of a struct or trait cannot be inferred. In that +case it is not always possible to use a type annotation, because all candidates +have the same return type. For instance: + +```compile_fail,E0282 +struct Foo { + num: T, +} + +impl Foo { + fn bar() -> i32 { + 0 + } + + fn baz() { + let number = Foo::bar(); + } +} +``` + +This will fail because the compiler does not know which instance of `Foo` to +call `bar` on. Change `Foo::bar()` to `Foo::::bar()` to resolve the error. diff --git a/src/librustc_error_codes/error_codes/E0283.md b/src/librustc_error_codes/error_codes/E0283.md new file mode 100644 index 0000000000..075f8b2e3b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0283.md @@ -0,0 +1,49 @@ +This error occurs when the compiler doesn't have enough information +to unambiguously choose an implementation. + +For example: + +```compile_fail,E0283 +trait Generator { + fn create() -> u32; +} + +struct Impl; + +impl Generator for Impl { + fn create() -> u32 { 1 } +} + +struct AnotherImpl; + +impl Generator for AnotherImpl { + fn create() -> u32 { 2 } +} + +fn main() { + let cont: u32 = Generator::create(); + // error, impossible to choose one of Generator trait implementation + // Should it be Impl or AnotherImpl, maybe something else? +} +``` + +To resolve this error use the concrete type: + +``` +trait Generator { + fn create() -> u32; +} + +struct AnotherImpl; + +impl Generator for AnotherImpl { + fn create() -> u32 { 2 } +} + +fn main() { + let gen1 = AnotherImpl::create(); + + // if there are multiple methods with same name (different traits) + let gen2 = ::create(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0284.md b/src/librustc_error_codes/error_codes/E0284.md new file mode 100644 index 0000000000..a1ffa2bda0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0284.md @@ -0,0 +1,42 @@ +This error occurs when the compiler is unable to unambiguously infer the +return type of a function or method which is generic on return type, such +as the `collect` method for `Iterator`s. + +For example: + +```compile_fail,E0284 +fn foo() -> Result { + let results = [Ok(true), Ok(false), Err(())].iter().cloned(); + let v: Vec = results.collect()?; + // Do things with v... + Ok(true) +} +``` + +Here we have an iterator `results` over `Result`. +Hence, `results.collect()` can return any type implementing +`FromIterator>`. On the other hand, the +`?` operator can accept any type implementing `Try`. + +The author of this code probably wants `collect()` to return a +`Result, ()>`, but the compiler can't be sure +that there isn't another type `T` implementing both `Try` and +`FromIterator>` in scope such that +`T::Ok == Vec`. Hence, this code is ambiguous and an error +is returned. + +To resolve this error, use a concrete type for the intermediate expression: + +``` +fn foo() -> Result { + let results = [Ok(true), Ok(false), Err(())].iter().cloned(); + let v = { + let temp: Result, ()> = results.collect(); + temp? + }; + // Do things with v... + Ok(true) +} +``` + +Note that the type of `v` can now be inferred from the type of `temp`. diff --git a/src/librustc_error_codes/error_codes/E0297.md b/src/librustc_error_codes/error_codes/E0297.md new file mode 100644 index 0000000000..66c31376d8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0297.md @@ -0,0 +1,40 @@ +#### Note: this error code is no longer emitted by the compiler. + +Patterns used to bind names must be irrefutable. That is, they must guarantee +that a name will be extracted in all cases. Instead of pattern matching the +loop variable, consider using a `match` or `if let` inside the loop body. For +instance: + +```compile_fail,E0005 +let xs : Vec> = vec![Some(1), None]; + +// This fails because `None` is not covered. +for Some(x) in xs { + // ... +} +``` + +Match inside the loop instead: + +``` +let xs : Vec> = vec![Some(1), None]; + +for item in xs { + match item { + Some(x) => {}, + None => {}, + } +} +``` + +Or use `if let`: + +``` +let xs : Vec> = vec![Some(1), None]; + +for item in xs { + if let Some(x) = item { + // ... + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0301.md b/src/librustc_error_codes/error_codes/E0301.md new file mode 100644 index 0000000000..485e19fbb8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0301.md @@ -0,0 +1,17 @@ +#### Note: this error code is no longer emitted by the compiler. + +Mutable borrows are not allowed in pattern guards, because matching cannot have +side effects. Side effects could alter the matched object or the environment +on which the match depends in such a way, that the match would not be +exhaustive. For instance, the following would not match any arm if mutable +borrows were allowed: + +```compile_fail,E0596 +match Some(()) { + None => { }, + option if option.take().is_none() => { + /* impossible, option is `Some` */ + }, + Some(_) => { } // When the previous match failed, the option became `None`. +} +``` diff --git a/src/librustc_error_codes/error_codes/E0302.md b/src/librustc_error_codes/error_codes/E0302.md new file mode 100644 index 0000000000..e6ac9d590c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0302.md @@ -0,0 +1,15 @@ +#### Note: this error code is no longer emitted by the compiler. + +Assignments are not allowed in pattern guards, because matching cannot have +side effects. Side effects could alter the matched object or the environment +on which the match depends in such a way, that the match would not be +exhaustive. For instance, the following would not match any arm if assignments +were allowed: + +```compile_fail,E0594 +match Some(()) { + None => { }, + option if { option = None; false } => { }, + Some(_) => { } // When the previous match failed, the option became `None`. +} +``` diff --git a/src/librustc_error_codes/error_codes/E0303.md b/src/librustc_error_codes/error_codes/E0303.md new file mode 100644 index 0000000000..20a6c078f4 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0303.md @@ -0,0 +1,28 @@ +In certain cases it is possible for sub-bindings to violate memory safety. +Updates to the borrow checker in a future version of Rust may remove this +restriction, but for now patterns must be rewritten without sub-bindings. + +Before: + +```compile_fail,E0303 +match Some("hi".to_string()) { + ref op_string_ref @ Some(s) => {}, + None => {}, +} +``` + +After: + +``` +match Some("hi".to_string()) { + Some(ref s) => { + let op_string_ref = &Some(s); + // ... + }, + None => {}, +} +``` + +The `op_string_ref` binding has type `&Option<&String>` in both cases. + +See also https://github.com/rust-lang/rust/issues/14587 diff --git a/src/librustc_error_codes/error_codes/E0307.md b/src/librustc_error_codes/error_codes/E0307.md new file mode 100644 index 0000000000..1779e5dbb3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0307.md @@ -0,0 +1,78 @@ +This error indicates that the `self` parameter in a method has an invalid +"receiver type". + +Methods take a special first parameter, of which there are three variants: +`self`, `&self`, and `&mut self`. These are syntactic sugar for +`self: Self`, `self: &Self`, and `self: &mut Self` respectively. + +``` +# struct Foo; +trait Trait { + fn foo(&self); +// ^^^^^ `self` here is a reference to the receiver object +} + +impl Trait for Foo { + fn foo(&self) {} +// ^^^^^ the receiver type is `&Foo` +} +``` + +The type `Self` acts as an alias to the type of the current trait +implementer, or "receiver type". Besides the already mentioned `Self`, +`&Self` and `&mut Self` valid receiver types, the following are also valid: +`self: Box`, `self: Rc`, `self: Arc`, and `self: Pin

` +(where P is one of the previous types except `Self`). Note that `Self` can +also be the underlying implementing type, like `Foo` in the following +example: + +``` +# struct Foo; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Foo { + fn foo(self: &Foo) {} +} +``` + +E0307 will be emitted by the compiler when using an invalid reciver type, +like in the following example: + +```compile_fail,E0307 +# struct Foo; +# struct Bar; +# trait Trait { +# fn foo(&self); +# } +impl Trait for Foo { + fn foo(self: &Bar) {} +} +``` + +The nightly feature [Arbintrary self types][AST] extends the accepted +set of receiver types to also include any type that can dereference to +`Self`: + +``` +#![feature(arbitrary_self_types)] + +struct Foo; +struct Bar; + +// Because you can dereference `Bar` into `Foo`... +impl std::ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &Foo + } +} + +impl Foo { + fn foo(self: Bar) {} +// ^^^^^^^^^ ...it can be used as the receiver type +} +``` + +[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html diff --git a/src/librustc_error_codes/error_codes/E0308.md b/src/librustc_error_codes/error_codes/E0308.md new file mode 100644 index 0000000000..a907ca2729 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0308.md @@ -0,0 +1,17 @@ +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can occur for several cases, the most common of which is a +mismatch in the expected type that the compiler inferred for a variable's +initializing expression, and the actual type explicitly assigned to the +variable. + +For example: + +```compile_fail,E0308 +let x: i32 = "I am not a number!"; +// ~~~ ~~~~~~~~~~~~~~~~~~~~ +// | | +// | initializing expression; +// | compiler infers type `&str` +// | +// type `i32` assigned to variable `x` +``` diff --git a/src/librustc_error_codes/error_codes/E0309.md b/src/librustc_error_codes/error_codes/E0309.md new file mode 100644 index 0000000000..73ce740747 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0309.md @@ -0,0 +1,50 @@ +The type definition contains some field whose type +requires an outlives annotation. Outlives annotations +(e.g., `T: 'a`) are used to guarantee that all the data in T is valid +for at least the lifetime `'a`. This scenario most commonly +arises when the type contains an associated type reference +like `>::Output`, as shown in this example: + +```compile_fail,E0309 +// This won't compile because the applicable impl of +// `SomeTrait` (below) requires that `T: 'a`, but the struct does +// not have a matching where-clause. +struct Foo<'a, T> { + foo: >::Output, +} + +trait SomeTrait<'a> { + type Output; +} + +impl<'a, T> SomeTrait<'a> for T +where + T: 'a, +{ + type Output = u32; +} +``` + +Here, the where clause `T: 'a` that appears on the impl is not known to be +satisfied on the struct. To make this example compile, you have to add +a where-clause like `T: 'a` to the struct definition: + +``` +struct Foo<'a, T> +where + T: 'a, +{ + foo: >::Output +} + +trait SomeTrait<'a> { + type Output; +} + +impl<'a, T> SomeTrait<'a> for T +where + T: 'a, +{ + type Output = u32; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0310.md b/src/librustc_error_codes/error_codes/E0310.md new file mode 100644 index 0000000000..be87ccb114 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0310.md @@ -0,0 +1,20 @@ +Types in type definitions have lifetimes associated with them that represent +how long the data stored within them is guaranteed to be live. This lifetime +must be as long as the data needs to be alive, and missing the constraint that +denotes this will cause this error. + +```compile_fail,E0310 +// This won't compile because T is not constrained to the static lifetime +// the reference needs +struct Foo { + foo: &'static T +} +``` + +This will compile, because it has the constraint on the type parameter: + +``` +struct Foo { + foo: &'static T +} +``` diff --git a/src/librustc_error_codes/error_codes/E0312.md b/src/librustc_error_codes/error_codes/E0312.md new file mode 100644 index 0000000000..cb090d0138 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0312.md @@ -0,0 +1,30 @@ +Reference's lifetime of borrowed content doesn't match the expected lifetime. + +Erroneous code example: + +```compile_fail,E0312 +pub fn opt_str<'a>(maybestr: &'a Option) -> &'static str { + if maybestr.is_none() { + "(none)" + } else { + let s: &'a str = maybestr.as_ref().unwrap(); + s // Invalid lifetime! + } +} +``` + +To fix this error, either lessen the expected lifetime or find a way to not have +to use this reference outside of its current scope (by running the code directly +in the same block for example?): + +``` +// In this case, we can fix the issue by switching from "static" lifetime to 'a +pub fn opt_str<'a>(maybestr: &'a Option) -> &'a str { + if maybestr.is_none() { + "(none)" + } else { + let s: &'a str = maybestr.as_ref().unwrap(); + s // Ok! + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0317.md b/src/librustc_error_codes/error_codes/E0317.md new file mode 100644 index 0000000000..e31a2b56be --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0317.md @@ -0,0 +1,14 @@ +This error occurs when an `if` expression without an `else` block is used in a +context where a type other than `()` is expected, for example a `let` +expression: + +```compile_fail,E0317 +fn main() { + let x = 5; + let a = if x == 5 { 1 }; +} +``` + +An `if` expression without an `else` block has the type `()`, so this is a type +error. To resolve it, add an `else` block having the same type as the `if` +block. diff --git a/src/librustc_error_codes/error_codes/E0321.md b/src/librustc_error_codes/error_codes/E0321.md new file mode 100644 index 0000000000..49cec94430 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0321.md @@ -0,0 +1,19 @@ +A cross-crate opt-out trait was implemented on something which wasn't a struct +or enum type. Erroneous code example: + +```compile_fail,E0321 +#![feature(optin_builtin_traits)] + +struct Foo; + +impl !Sync for Foo {} + +unsafe impl Send for &'static Foo {} +// error: cross-crate traits with a default impl, like `core::marker::Send`, +// can only be implemented for a struct/enum type, not +// `&'static Foo` +``` + +Only structs and enums are permitted to impl Send, Sync, and other opt-out +trait, and the struct or enum must be local to the current crate. So, for +example, `unsafe impl Send for Rc` is not allowed. diff --git a/src/librustc_error_codes/error_codes/E0322.md b/src/librustc_error_codes/error_codes/E0322.md new file mode 100644 index 0000000000..d2ee426763 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0322.md @@ -0,0 +1,4 @@ +The `Sized` trait is a special trait built-in to the compiler for types with a +constant size known at compile-time. This trait is automatically implemented +for types as needed by the compiler, and it is currently disallowed to +explicitly implement it for a type. diff --git a/src/librustc_error_codes/error_codes/E0323.md b/src/librustc_error_codes/error_codes/E0323.md new file mode 100644 index 0000000000..6d34c35f9c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0323.md @@ -0,0 +1,45 @@ +An associated const was implemented when another trait item was expected. +Erroneous code example: + +```compile_fail,E0323 +trait Foo { + type N; +} + +struct Bar; + +impl Foo for Bar { + const N : u32 = 0; + // error: item `N` is an associated const, which doesn't match its + // trait `` +} +``` + +Please verify that the associated const wasn't misspelled and the correct trait +was implemented. Example: + +``` +struct Bar; + +trait Foo { + type N; +} + +impl Foo for Bar { + type N = u32; // ok! +} +``` + +Or: + +``` +struct Bar; + +trait Foo { + const N : u32; +} + +impl Foo for Bar { + const N : u32 = 0; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0324.md b/src/librustc_error_codes/error_codes/E0324.md new file mode 100644 index 0000000000..b8c9e59699 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0324.md @@ -0,0 +1,37 @@ +A method was implemented when another trait item was expected. Erroneous +code example: + +```compile_fail,E0324 +struct Bar; + +trait Foo { + const N : u32; + + fn M(); +} + +impl Foo for Bar { + fn N() {} + // error: item `N` is an associated method, which doesn't match its + // trait `` +} +``` + +To fix this error, please verify that the method name wasn't misspelled and +verify that you are indeed implementing the correct trait items. Example: + +``` +struct Bar; + +trait Foo { + const N : u32; + + fn M(); +} + +impl Foo for Bar { + const N : u32 = 0; + + fn M() {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0325.md b/src/librustc_error_codes/error_codes/E0325.md new file mode 100644 index 0000000000..f685b92cbf --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0325.md @@ -0,0 +1,45 @@ +An associated type was implemented when another trait item was expected. +Erroneous code example: + +```compile_fail,E0325 +struct Bar; + +trait Foo { + const N : u32; +} + +impl Foo for Bar { + type N = u32; + // error: item `N` is an associated type, which doesn't match its + // trait `` +} +``` + +Please verify that the associated type name wasn't misspelled and your +implementation corresponds to the trait definition. Example: + +``` +struct Bar; + +trait Foo { + type N; +} + +impl Foo for Bar { + type N = u32; // ok! +} +``` + +Or: + +``` +struct Bar; + +trait Foo { + const N : u32; +} + +impl Foo for Bar { + const N : u32 = 0; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0326.md b/src/librustc_error_codes/error_codes/E0326.md new file mode 100644 index 0000000000..0702d00c2d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0326.md @@ -0,0 +1,16 @@ +The types of any associated constants in a trait implementation must match the +types in the trait definition. This error indicates that there was a mismatch. + +Here's an example of this error: + +```compile_fail,E0326 +trait Foo { + const BAR: bool; +} + +struct Bar; + +impl Foo for Bar { + const BAR: u32 = 5; // error, expected bool, found u32 +} +``` diff --git a/src/librustc_error_codes/error_codes/E0328.md b/src/librustc_error_codes/error_codes/E0328.md new file mode 100644 index 0000000000..8390923545 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0328.md @@ -0,0 +1,34 @@ +The Unsize trait should not be implemented directly. All implementations of +Unsize are provided automatically by the compiler. + +Erroneous code example: + +```compile_fail,E0328 +#![feature(unsize)] + +use std::marker::Unsize; + +pub struct MyType; + +impl Unsize for MyType {} +``` + +If you are defining your own smart pointer type and would like to enable +conversion from a sized to an unsized type with the +[DST coercion system][RFC 982], use [`CoerceUnsized`] instead. + +``` +#![feature(coerce_unsized)] + +use std::ops::CoerceUnsized; + +pub struct MyType { + field_with_unsized_type: T, +} + +impl CoerceUnsized> for MyType + where T: CoerceUnsized {} +``` + +[RFC 982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +[`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html diff --git a/src/librustc_error_codes/error_codes/E0329.md b/src/librustc_error_codes/error_codes/E0329.md new file mode 100644 index 0000000000..37d84a1a89 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0329.md @@ -0,0 +1,40 @@ +#### Note: this error code is no longer emitted by the compiler. + +An attempt was made to access an associated constant through either a generic +type parameter or `Self`. This is not supported yet. An example causing this +error is shown below: + +``` +trait Foo { + const BAR: f64; +} + +struct MyStruct; + +impl Foo for MyStruct { + const BAR: f64 = 0f64; +} + +fn get_bar_bad(t: F) -> f64 { + F::BAR +} +``` + +Currently, the value of `BAR` for a particular type can only be accessed +through a concrete type, as shown below: + +``` +trait Foo { + const BAR: f64; +} + +struct MyStruct; + +impl Foo for MyStruct { + const BAR: f64 = 0f64; +} + +fn get_bar_good() -> f64 { + ::BAR +} +``` diff --git a/src/librustc_error_codes/error_codes/E0364.md b/src/librustc_error_codes/error_codes/E0364.md new file mode 100644 index 0000000000..0cca8f58b1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0364.md @@ -0,0 +1,32 @@ +Private items cannot be publicly re-exported. This error indicates that you +attempted to `pub use` a type or value that was not itself public. + +Erroneous code example: + +```compile_fail +mod foo { + const X: u32 = 1; +} + +pub use foo::X; + +fn main() {} +``` + +The solution to this problem is to ensure that the items that you are +re-exporting are themselves marked with `pub`: + +``` +mod foo { + pub const X: u32 = 1; +} + +pub use foo::X; + +fn main() {} +``` + +See the 'Use Declarations' section of the reference for more information on +this topic: + +https://doc.rust-lang.org/reference.html#use-declarations diff --git a/src/librustc_error_codes/error_codes/E0365.md b/src/librustc_error_codes/error_codes/E0365.md new file mode 100644 index 0000000000..8f90d949e3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0365.md @@ -0,0 +1,32 @@ +Private modules cannot be publicly re-exported. This error indicates that you +attempted to `pub use` a module that was not itself public. + +Erroneous code example: + +```compile_fail,E0365 +mod foo { + pub const X: u32 = 1; +} + +pub use foo as foo2; + +fn main() {} +``` + +The solution to this problem is to ensure that the module that you are +re-exporting is itself marked with `pub`: + +``` +pub mod foo { + pub const X: u32 = 1; +} + +pub use foo as foo2; + +fn main() {} +``` + +See the 'Use Declarations' section of the reference for more information +on this topic: + +https://doc.rust-lang.org/reference.html#use-declarations diff --git a/src/librustc_error_codes/error_codes/E0366.md b/src/librustc_error_codes/error_codes/E0366.md new file mode 100644 index 0000000000..e6f8e61893 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0366.md @@ -0,0 +1,30 @@ +An attempt was made to implement `Drop` on a concrete specialization of a +generic type. An example is shown below: + +```compile_fail,E0366 +struct Foo { + t: T +} + +impl Drop for Foo { + fn drop(&mut self) {} +} +``` + +This code is not legal: it is not possible to specialize `Drop` to a subset of +implementations of a generic type. One workaround for this is to wrap the +generic type, as shown below: + +``` +struct Foo { + t: T +} + +struct Bar { + t: Foo +} + +impl Drop for Bar { + fn drop(&mut self) {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0367.md b/src/librustc_error_codes/error_codes/E0367.md new file mode 100644 index 0000000000..7d661b2f03 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0367.md @@ -0,0 +1,35 @@ +An attempt was made to implement `Drop` on a specialization of a generic type. +An example is shown below: + +```compile_fail,E0367 +trait Foo{} + +struct MyStruct { + t: T +} + +impl Drop for MyStruct { + fn drop(&mut self) {} +} +``` + +This code is not legal: it is not possible to specialize `Drop` to a subset of +implementations of a generic type. In order for this code to work, `MyStruct` +must also require that `T` implements `Foo`. Alternatively, another option is +to wrap the generic type in another that specializes appropriately: + +``` +trait Foo{} + +struct MyStruct { + t: T +} + +struct MyStructWrapper { + t: MyStruct +} + +impl Drop for MyStructWrapper { + fn drop(&mut self) {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0368.md b/src/librustc_error_codes/error_codes/E0368.md new file mode 100644 index 0000000000..0bb283258c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0368.md @@ -0,0 +1,47 @@ +This error indicates that a binary assignment operator like `+=` or `^=` was +applied to a type that doesn't support it. For example: + +```compile_fail,E0368 +let mut x = 12f32; // error: binary operation `<<` cannot be applied to + // type `f32` + +x <<= 2; +``` + +To fix this error, please check that this type implements this binary +operation. Example: + +``` +let mut x = 12u32; // the `u32` type does implement the `ShlAssign` trait + +x <<= 2; // ok! +``` + +It is also possible to overload most operators for your own type by +implementing the `[OP]Assign` traits from `std::ops`. + +Another problem you might be facing is this: suppose you've overloaded the `+` +operator for some type `Foo` by implementing the `std::ops::Add` trait for +`Foo`, but you find that using `+=` does not work, as in this example: + +```compile_fail,E0368 +use std::ops::Add; + +struct Foo(u32); + +impl Add for Foo { + type Output = Foo; + + fn add(self, rhs: Foo) -> Foo { + Foo(self.0 + rhs.0) + } +} + +fn main() { + let mut x: Foo = Foo(5); + x += Foo(7); // error, `+= cannot be applied to the type `Foo` +} +``` + +This is because `AddAssign` is not automatically implemented, so you need to +manually implement it for your type. diff --git a/src/librustc_error_codes/error_codes/E0369.md b/src/librustc_error_codes/error_codes/E0369.md new file mode 100644 index 0000000000..397979e564 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0369.md @@ -0,0 +1,28 @@ +A binary operation was attempted on a type which doesn't support it. +Erroneous code example: + +```compile_fail,E0369 +let x = 12f32; // error: binary operation `<<` cannot be applied to + // type `f32` + +x << 2; +``` + +To fix this error, please check that this type implements this binary +operation. Example: + +``` +let x = 12u32; // the `u32` type does implement it: + // https://doc.rust-lang.org/stable/std/ops/trait.Shl.html + +x << 2; // ok! +``` + +It is also possible to overload most operators for your own type by +implementing traits from `std::ops`. + +String concatenation appends the string on the right to the string on the +left and may require reallocation. This requires ownership of the string +on the left. If something should be added to a string literal, move the +literal to the heap by allocating it with `to_owned()` like in +`"Your text".to_owned()`. diff --git a/src/librustc_error_codes/error_codes/E0370.md b/src/librustc_error_codes/error_codes/E0370.md new file mode 100644 index 0000000000..a3d280fc6d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0370.md @@ -0,0 +1,33 @@ +The maximum value of an enum was reached, so it cannot be automatically +set in the next enum value. Erroneous code example: + +```compile_fail,E0370 +#[repr(i64)] +enum Foo { + X = 0x7fffffffffffffff, + Y, // error: enum discriminant overflowed on value after + // 9223372036854775807: i64; set explicitly via + // Y = -9223372036854775808 if that is desired outcome +} +``` + +To fix this, please set manually the next enum value or put the enum variant +with the maximum value at the end of the enum. Examples: + +``` +#[repr(i64)] +enum Foo { + X = 0x7fffffffffffffff, + Y = 0, // ok! +} +``` + +Or: + +``` +#[repr(i64)] +enum Foo { + Y = 0, // ok! + X = 0x7fffffffffffffff, +} +``` diff --git a/src/librustc_error_codes/error_codes/E0371.md b/src/librustc_error_codes/error_codes/E0371.md new file mode 100644 index 0000000000..9363cddb1d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0371.md @@ -0,0 +1,17 @@ +When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a +definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement +`Trait1` for `Trait2`. This is because `Trait2` already implements `Trait1` by +definition, so it is not useful to do this. + +Example: + +```compile_fail,E0371 +trait Foo { fn foo(&self) { } } +trait Bar: Foo { } +trait Baz: Bar { } + +impl Bar for Baz { } // error, `Baz` implements `Bar` by definition +impl Foo for Baz { } // error, `Baz` implements `Bar` which implements `Foo` +impl Baz for Baz { } // error, `Baz` (trivially) implements `Baz` +impl Baz for Bar { } // Note: This is OK +``` diff --git a/src/librustc_error_codes/error_codes/E0373.md b/src/librustc_error_codes/error_codes/E0373.md new file mode 100644 index 0000000000..47e3a48f03 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0373.md @@ -0,0 +1,48 @@ +This error occurs when an attempt is made to use data captured by a closure, +when that data may no longer exist. It's most commonly seen when attempting to +return a closure: + +```compile_fail,E0373 +fn foo() -> Box u32> { + let x = 0u32; + Box::new(|y| x + y) +} +``` + +Notice that `x` is stack-allocated by `foo()`. By default, Rust captures +closed-over data by reference. This means that once `foo()` returns, `x` no +longer exists. An attempt to access `x` within the closure would thus be +unsafe. + +Another situation where this might be encountered is when spawning threads: + +```compile_fail,E0373 +fn foo() { + let x = 0u32; + let y = 1u32; + + let thr = std::thread::spawn(|| { + x + y + }); +} +``` + +Since our new thread runs in parallel, the stack frame containing `x` and `y` +may well have disappeared by the time we try to use them. Even if we call +`thr.join()` within foo (which blocks until `thr` has completed, ensuring the +stack frame won't disappear), we will not succeed: the compiler cannot prove +that this behaviour is safe, and so won't let us do it. + +The solution to this problem is usually to switch to using a `move` closure. +This approach moves (or copies, where possible) data into the closure, rather +than taking references to it. For example: + +``` +fn foo() -> Box u32> { + let x = 0u32; + Box::new(move |y| x + y) +} +``` + +Now that the closure has its own copy of the data, there's no need to worry +about safety. diff --git a/src/librustc_error_codes/error_codes/E0374.md b/src/librustc_error_codes/error_codes/E0374.md new file mode 100644 index 0000000000..0e1a4bf809 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0374.md @@ -0,0 +1,55 @@ +A struct without a field containing an unsized type cannot implement +`CoerceUnsized`. An [unsized type][1] is any type that the compiler +doesn't know the length or alignment of at compile time. Any struct +containing an unsized type is also unsized. + +[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait + +Example of erroneous code: + +```compile_fail,E0374 +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: i32, +} + +// error: Struct `Foo` has no unsized fields that need `CoerceUnsized`. +impl CoerceUnsized> for Foo + where T: CoerceUnsized {} +``` + +`CoerceUnsized` is used to coerce one struct containing an unsized type +into another struct containing a different unsized type. If the struct +doesn't have any fields of unsized types then you don't need explicit +coercion to get the types you want. To fix this you can either +not try to implement `CoerceUnsized` or you can add a field that is +unsized to the struct. + +Example: + +``` +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +// We don't need to impl `CoerceUnsized` here. +struct Foo { + a: i32, +} + +// We add the unsized type field to the struct. +struct Bar { + a: i32, + b: T, +} + +// The struct has an unsized field so we can implement +// `CoerceUnsized` for it. +impl CoerceUnsized> for Bar + where T: CoerceUnsized {} +``` + +Note that `CoerceUnsized` is mainly used by smart pointers like `Box`, `Rc` +and `Arc` to be able to mark that they can coerce unsized types that they +are pointing at. diff --git a/src/librustc_error_codes/error_codes/E0375.md b/src/librustc_error_codes/error_codes/E0375.md new file mode 100644 index 0000000000..31fcd85cb0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0375.md @@ -0,0 +1,52 @@ +A struct with more than one field containing an unsized type cannot implement +`CoerceUnsized`. This only occurs when you are trying to coerce one of the +types in your struct to another type in the struct. In this case we try to +impl `CoerceUnsized` from `T` to `U` which are both types that the struct +takes. An [unsized type][1] is any type that the compiler doesn't know the +length or alignment of at compile time. Any struct containing an unsized type +is also unsized. + +Example of erroneous code: + +```compile_fail,E0375 +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: i32, + b: T, + c: U, +} + +// error: Struct `Foo` has more than one unsized field. +impl CoerceUnsized> for Foo {} +``` + +`CoerceUnsized` only allows for coercion from a structure with a single +unsized type field to another struct with a single unsized type field. +In fact Rust only allows for a struct to have one unsized type in a struct +and that unsized type must be the last field in the struct. So having two +unsized types in a single struct is not allowed by the compiler. To fix this +use only one field containing an unsized type in the struct and then use +multiple structs to manage each unsized type field you need. + +Example: + +``` +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: i32, + b: T, +} + +impl CoerceUnsized> for Foo + where T: CoerceUnsized {} + +fn coerce_foo, U>(t: T) -> Foo { + Foo { a: 12i32, b: t } // we use coercion to get the `Foo` type we need +} +``` + +[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait diff --git a/src/librustc_error_codes/error_codes/E0376.md b/src/librustc_error_codes/error_codes/E0376.md new file mode 100644 index 0000000000..b028aab458 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0376.md @@ -0,0 +1,45 @@ +The type you are trying to impl `CoerceUnsized` for is not a struct. +`CoerceUnsized` can only be implemented for a struct. Unsized types are +already able to be coerced without an implementation of `CoerceUnsized` +whereas a struct containing an unsized type needs to know the unsized type +field it's containing is able to be coerced. An [unsized type][1] +is any type that the compiler doesn't know the length or alignment of at +compile time. Any struct containing an unsized type is also unsized. + +[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait + +Example of erroneous code: + +```compile_fail,E0376 +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: T, +} + +// error: The type `U` is not a struct +impl CoerceUnsized for Foo {} +``` + +The `CoerceUnsized` trait takes a struct type. Make sure the type you are +providing to `CoerceUnsized` is a struct with only the last field containing an +unsized type. + +Example: + +``` +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: T, +} + +// The `Foo` is a struct so `CoerceUnsized` can be implemented +impl CoerceUnsized> for Foo where T: CoerceUnsized {} +``` + +Note that in Rust, structs can only contain an unsized type if the field +containing the unsized type is the last and only unsized type field in the +struct. diff --git a/src/librustc_error_codes/error_codes/E0378.md b/src/librustc_error_codes/error_codes/E0378.md new file mode 100644 index 0000000000..311483c890 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0378.md @@ -0,0 +1,57 @@ +The `DispatchFromDyn` trait currently can only be implemented for +builtin pointer types and structs that are newtype wrappers around them +— that is, the struct must have only one field (except for`PhantomData`), +and that field must itself implement `DispatchFromDyn`. + +Examples: + +``` +#![feature(dispatch_from_dyn, unsize)] +use std::{ + marker::Unsize, + ops::DispatchFromDyn, +}; + +struct Ptr(*const T); + +impl DispatchFromDyn> for Ptr +where + T: Unsize, +{} +``` + +``` +#![feature(dispatch_from_dyn)] +use std::{ + ops::DispatchFromDyn, + marker::PhantomData, +}; + +struct Wrapper { + ptr: T, + _phantom: PhantomData<()>, +} + +impl DispatchFromDyn> for Wrapper +where + T: DispatchFromDyn, +{} +``` + +Example of illegal `DispatchFromDyn` implementation +(illegal because of extra field) + +```compile-fail,E0378 +#![feature(dispatch_from_dyn)] +use std::ops::DispatchFromDyn; + +struct WrapperExtraField { + ptr: T, + extra_stuff: i32, +} + +impl DispatchFromDyn> for WrapperExtraField +where + T: DispatchFromDyn, +{} +``` diff --git a/src/librustc_error_codes/error_codes/E0379.md b/src/librustc_error_codes/error_codes/E0379.md new file mode 100644 index 0000000000..3503da6ac2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0379.md @@ -0,0 +1,4 @@ +Trait methods cannot be declared `const` by design. For more information, see +[RFC 911]. + +[RFC 911]: https://github.com/rust-lang/rfcs/pull/911 diff --git a/src/librustc_error_codes/error_codes/E0380.md b/src/librustc_error_codes/error_codes/E0380.md new file mode 100644 index 0000000000..fe5de56933 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0380.md @@ -0,0 +1,4 @@ +Auto traits cannot have methods or associated items. +For more information see the [opt-in builtin traits RFC][RFC 19]. + +[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md diff --git a/src/librustc_error_codes/error_codes/E0381.md b/src/librustc_error_codes/error_codes/E0381.md new file mode 100644 index 0000000000..9767800992 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0381.md @@ -0,0 +1,20 @@ +It is not allowed to use or capture an uninitialized variable. + +Erroneous code example: + +```compile_fail,E0381 +fn main() { + let x: i32; + let y = x; // error, use of possibly-uninitialized variable +} +``` + +To fix this, ensure that any declared variables are initialized before being +used. Example: + +``` +fn main() { + let x: i32 = 0; + let y = x; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0382.md b/src/librustc_error_codes/error_codes/E0382.md new file mode 100644 index 0000000000..1592eac2ec --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0382.md @@ -0,0 +1,110 @@ +This error occurs when an attempt is made to use a variable after its contents +have been moved elsewhere. + +Erroneous code example: + +```compile_fail,E0382 +struct MyStruct { s: u32 } + +fn main() { + let mut x = MyStruct{ s: 5u32 }; + let y = x; + x.s = 6; + println!("{}", x.s); +} +``` + +Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out +of `x` when we set `y`. This is fundamental to Rust's ownership system: outside +of workarounds like `Rc`, a value cannot be owned by more than one variable. + +Sometimes we don't need to move the value. Using a reference, we can let another +function borrow the value without changing its ownership. In the example below, +we don't actually have to move our string to `calculate_length`, we can give it +a reference to it with `&` instead. + +``` +fn main() { + let s1 = String::from("hello"); + + let len = calculate_length(&s1); + + println!("The length of '{}' is {}.", s1, len); +} + +fn calculate_length(s: &String) -> usize { + s.len() +} +``` + +A mutable reference can be created with `&mut`. + +Sometimes we don't want a reference, but a duplicate. All types marked `Clone` +can be duplicated by calling `.clone()`. Subsequent changes to a clone do not +affect the original variable. + +Most types in the standard library are marked `Clone`. The example below +demonstrates using `clone()` on a string. `s1` is first set to "many", and then +copied to `s2`. Then the first character of `s1` is removed, without affecting +`s2`. "any many" is printed to the console. + +``` +fn main() { + let mut s1 = String::from("many"); + let s2 = s1.clone(); + s1.remove(0); + println!("{} {}", s1, s2); +} +``` + +If we control the definition of a type, we can implement `Clone` on it ourselves +with `#[derive(Clone)]`. + +Some types have no ownership semantics at all and are trivial to duplicate. An +example is `i32` and the other number types. We don't have to call `.clone()` to +clone them, because they are marked `Copy` in addition to `Clone`. Implicit +cloning is more convenient in this case. We can mark our own types `Copy` if +all their members also are marked `Copy`. + +In the example below, we implement a `Point` type. Because it only stores two +integers, we opt-out of ownership semantics with `Copy`. Then we can +`let p2 = p1` without `p1` being moved. + +``` +#[derive(Copy, Clone)] +struct Point { x: i32, y: i32 } + +fn main() { + let mut p1 = Point{ x: -1, y: 2 }; + let p2 = p1; + p1.x = 1; + println!("p1: {}, {}", p1.x, p1.y); + println!("p2: {}, {}", p2.x, p2.y); +} +``` + +Alternatively, if we don't control the struct's definition, or mutable shared +ownership is truly required, we can use `Rc` and `RefCell`: + +``` +use std::cell::RefCell; +use std::rc::Rc; + +struct MyStruct { s: u32 } + +fn main() { + let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 })); + let y = x.clone(); + x.borrow_mut().s = 6; + println!("{}", x.borrow().s); +} +``` + +With this approach, x and y share ownership of the data via the `Rc` (reference +count type). `RefCell` essentially performs runtime borrow checking: ensuring +that at most one writer or multiple readers can access the data at any one time. + +If you wish to learn more about ownership in Rust, start with the chapter in the +Book: + +https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html diff --git a/src/librustc_error_codes/error_codes/E0383.md b/src/librustc_error_codes/error_codes/E0383.md new file mode 100644 index 0000000000..fd2b0b08fb --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0383.md @@ -0,0 +1,34 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error occurs when an attempt is made to partially reinitialize a +structure that is currently uninitialized. + +For example, this can happen when a drop has taken place: + +```compile_fail +struct Foo { + a: u32, +} +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} + +let mut x = Foo { a: 1 }; +drop(x); // `x` is now uninitialized +x.a = 2; // error, partial reinitialization of uninitialized structure `t` +``` + +This error can be fixed by fully reinitializing the structure in question: + +``` +struct Foo { + a: u32, +} +impl Drop for Foo { + fn drop(&mut self) { /* ... */ } +} + +let mut x = Foo { a: 1 }; +drop(x); +x = Foo { a: 2 }; +``` diff --git a/src/librustc_error_codes/error_codes/E0384.md b/src/librustc_error_codes/error_codes/E0384.md new file mode 100644 index 0000000000..7c7ee744a8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0384.md @@ -0,0 +1,20 @@ +This error occurs when an attempt is made to reassign an immutable variable. + +Erroneous code example: + +```compile_fail,E0384 +fn main() { + let x = 3; + x = 5; // error, reassignment of immutable variable +} +``` + +By default, variables in Rust are immutable. To fix this error, add the keyword +`mut` after the keyword `let` when declaring the variable. For example: + +``` +fn main() { + let mut x = 3; + x = 5; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0386.md b/src/librustc_error_codes/error_codes/E0386.md new file mode 100644 index 0000000000..de3b468b6e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0386.md @@ -0,0 +1,31 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error occurs when an attempt is made to mutate the target of a mutable +reference stored inside an immutable container. + +For example, this can happen when storing a `&mut` inside an immutable `Box`: + +``` +let mut x: i64 = 1; +let y: Box<_> = Box::new(&mut x); +**y = 2; // error, cannot assign to data in an immutable container +``` + +This error can be fixed by making the container mutable: + +``` +let mut x: i64 = 1; +let mut y: Box<_> = Box::new(&mut x); +**y = 2; +``` + +It can also be fixed by using a type with interior mutability, such as `Cell` +or `RefCell`: + +``` +use std::cell::Cell; + +let x: i64 = 1; +let y: Box> = Box::new(Cell::new(x)); +y.set(2); +``` diff --git a/src/librustc_error_codes/error_codes/E0387.md b/src/librustc_error_codes/error_codes/E0387.md new file mode 100644 index 0000000000..3a5facfdd2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0387.md @@ -0,0 +1,57 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error occurs when an attempt is made to mutate or mutably reference data +that a closure has captured immutably. + +Erroneous code example: + +```compile_fail +// Accepts a function or a closure that captures its environment immutably. +// Closures passed to foo will not be able to mutate their closed-over state. +fn foo(f: F) { } + +// Attempts to mutate closed-over data. Error message reads: +// `cannot assign to data in a captured outer variable...` +fn mutable() { + let mut x = 0u32; + foo(|| x = 2); +} + +// Attempts to take a mutable reference to closed-over data. Error message +// reads: `cannot borrow data mutably in a captured outer variable...` +fn mut_addr() { + let mut x = 0u32; + foo(|| { let y = &mut x; }); +} +``` + +The problem here is that foo is defined as accepting a parameter of type `Fn`. +Closures passed into foo will thus be inferred to be of type `Fn`, meaning that +they capture their context immutably. + +If the definition of `foo` is under your control, the simplest solution is to +capture the data mutably. This can be done by defining `foo` to take FnMut +rather than Fn: + +``` +fn foo(f: F) { } +``` + +Alternatively, we can consider using the `Cell` and `RefCell` types to achieve +interior mutability through a shared reference. Our example's `mutable` +function could be redefined as below: + +``` +use std::cell::Cell; + +fn foo(f: F) { } + +fn mutable() { + let x = Cell::new(0u32); + foo(|| x.set(2)); +} +``` + +You can read more about cell types in the API documentation: + +https://doc.rust-lang.org/std/cell/ diff --git a/src/librustc_error_codes/error_codes/E0388.md b/src/librustc_error_codes/error_codes/E0388.md new file mode 100644 index 0000000000..512fb42e6e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0388.md @@ -0,0 +1 @@ +#### Note: this error code is no longer emitted by the compiler. diff --git a/src/librustc_error_codes/error_codes/E0389.md b/src/librustc_error_codes/error_codes/E0389.md new file mode 100644 index 0000000000..9f064e44c8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0389.md @@ -0,0 +1,63 @@ +#### Note: this error code is no longer emitted by the compiler. + +An attempt was made to mutate data using a non-mutable reference. This +commonly occurs when attempting to assign to a non-mutable reference of a +mutable reference (`&(&mut T)`). + +Erroneous code example: + +```compile_fail +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + let fancy_ref = &(&mut fancy); + fancy_ref.num = 6; // error: cannot assign to data in a `&` reference + println!("{}", fancy_ref.num); +} +``` + +Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an +immutable reference to a value borrows it immutably. There can be multiple +references of type `&(&mut T)` that point to the same value, so they must be +immutable to prevent multiple mutable references to the same value. + +To fix this, either remove the outer reference: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + + let fancy_ref = &mut fancy; + // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum) + + fancy_ref.num = 6; // No error! + + println!("{}", fancy_ref.num); +} +``` + +Or make the outer reference mutable: + +``` +struct FancyNum { + num: u8 +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + + let fancy_ref = &mut (&mut fancy); + // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum) + + fancy_ref.num = 6; // No error! + + println!("{}", fancy_ref.num); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0390.md b/src/librustc_error_codes/error_codes/E0390.md new file mode 100644 index 0000000000..9d05740d6f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0390.md @@ -0,0 +1,28 @@ +You tried to implement methods for a primitive type. Erroneous code example: + +```compile_fail,E0390 +struct Foo { + x: i32 +} + +impl *mut Foo {} +// error: only a single inherent implementation marked with +// `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive +``` + +This isn't allowed, but using a trait to implement a method is a good solution. +Example: + +``` +struct Foo { + x: i32 +} + +trait Bar { + fn bar(); +} + +impl Bar for *mut Foo { + fn bar() {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0391.md b/src/librustc_error_codes/error_codes/E0391.md new file mode 100644 index 0000000000..5db9ad16d0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0391.md @@ -0,0 +1,14 @@ +This error indicates that some types or traits depend on each other +and therefore cannot be constructed. + +The following example contains a circular dependency between two traits: + +```compile_fail,E0391 +trait FirstTrait : SecondTrait { + +} + +trait SecondTrait : FirstTrait { + +} +``` diff --git a/src/librustc_error_codes/error_codes/E0392.md b/src/librustc_error_codes/error_codes/E0392.md new file mode 100644 index 0000000000..1d93e904e3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0392.md @@ -0,0 +1,57 @@ +This error indicates that a type or lifetime parameter has been declared +but not actually used. Here is an example that demonstrates the error: + +```compile_fail,E0392 +enum Foo { + Bar, +} +``` + +If the type parameter was included by mistake, this error can be fixed +by simply removing the type parameter, as shown below: + +``` +enum Foo { + Bar, +} +``` + +Alternatively, if the type parameter was intentionally inserted, it must be +used. A simple fix is shown below: + +``` +enum Foo { + Bar(T), +} +``` + +This error may also commonly be found when working with unsafe code. For +example, when using raw pointers one may wish to specify the lifetime for +which the pointed-at data is valid. An initial attempt (below) causes this +error: + +```compile_fail,E0392 +struct Foo<'a, T> { + x: *const T, +} +``` + +We want to express the constraint that Foo should not outlive `'a`, because +the data pointed to by `T` is only valid for that lifetime. The problem is +that there are no actual uses of `'a`. It's possible to work around this +by adding a PhantomData type to the struct, using it to tell the compiler +to act as if the struct contained a borrowed reference `&'a T`: + +``` +use std::marker::PhantomData; + +struct Foo<'a, T: 'a> { + x: *const T, + phantom: PhantomData<&'a T> +} +``` + +[PhantomData] can also be used to express information about unused type +parameters. + +[PhantomData]: https://doc.rust-lang.org/std/marker/struct.PhantomData.html diff --git a/src/librustc_error_codes/error_codes/E0393.md b/src/librustc_error_codes/error_codes/E0393.md new file mode 100644 index 0000000000..7cce99401c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0393.md @@ -0,0 +1,28 @@ +A type parameter which references `Self` in its default value was not specified. +Example of erroneous code: + +```compile_fail,E0393 +trait A {} + +fn together_we_will_rule_the_galaxy(son: &A) {} +// error: the type parameter `T` must be explicitly specified in an +// object type because its default value `Self` references the +// type `Self` +``` + +A trait object is defined over a single, fully-defined trait. With a regular +default parameter, this parameter can just be substituted in. However, if the +default parameter is `Self`, the trait changes for each concrete type; i.e. +`i32` will be expected to implement `A`, `bool` will be expected to +implement `A`, etc... These types will not share an implementation of a +fully-defined trait; instead they share implementations of a trait with +different parameters substituted in for each implementation. This is +irreconcilable with what we need to make a trait object work, and is thus +disallowed. Making the trait concrete by explicitly specifying the value of the +defaulted parameter will fix this issue. Fixed example: + +``` +trait A {} + +fn together_we_will_rule_the_galaxy(son: &A) {} // Ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0398.md b/src/librustc_error_codes/error_codes/E0398.md new file mode 100644 index 0000000000..75d86979e3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0398.md @@ -0,0 +1,35 @@ +#### Note: this error code is no longer emitted by the compiler. + +In Rust 1.3, the default object lifetime bounds are expected to change, as +described in [RFC 1156]. You are getting a warning because the compiler +thinks it is possible that this change will cause a compilation error in your +code. It is possible, though unlikely, that this is a false alarm. + +The heart of the change is that where `&'a Box` used to default to +`&'a Box`, it now defaults to `&'a Box` (here, +`SomeTrait` is the name of some trait type). Note that the only types which are +affected are references to boxes, like `&Box` or +`&[Box]`. More common types like `&SomeTrait` or `Box` +are unaffected. + +To silence this warning, edit your code to use an explicit bound. Most of the +time, this means that you will want to change the signature of a function that +you are calling. For example, if the error is reported on a call like `foo(x)`, +and `foo` is defined as follows: + +``` +# trait SomeTrait {} +fn foo(arg: &Box) { /* ... */ } +``` + +You might change it to: + +``` +# trait SomeTrait {} +fn foo<'a>(arg: &'a Box) { /* ... */ } +``` + +This explicitly states that you expect the trait object `SomeTrait` to contain +references (with a maximum lifetime of `'a`). + +[RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md diff --git a/src/librustc_error_codes/error_codes/E0399.md b/src/librustc_error_codes/error_codes/E0399.md new file mode 100644 index 0000000000..71482c3ca6 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0399.md @@ -0,0 +1,35 @@ +You implemented a trait, overriding one or more of its associated types but did +not reimplement its default methods. + +Example of erroneous code: + +```compile_fail,E0399 +#![feature(associated_type_defaults)] + +pub trait Foo { + type Assoc = u8; + fn bar(&self) {} +} + +impl Foo for i32 { + // error - the following trait items need to be reimplemented as + // `Assoc` was overridden: `bar` + type Assoc = i32; +} +``` + +To fix this, add an implementation for each default method from the trait: + +``` +#![feature(associated_type_defaults)] + +pub trait Foo { + type Assoc = u8; + fn bar(&self) {} +} + +impl Foo for i32 { + type Assoc = i32; + fn bar(&self) {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0401.md b/src/librustc_error_codes/error_codes/E0401.md new file mode 100644 index 0000000000..4c93053d5f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0401.md @@ -0,0 +1,106 @@ +Inner items do not inherit type or const parameters from the functions +they are embedded in. + +Erroneous code example: + +```compile_fail,E0401 +fn foo(x: T) { + fn bar(y: T) { // T is defined in the "outer" function + // .. + } + bar(x); +} +``` + +Nor will this: + +```compile_fail,E0401 +fn foo(x: T) { + type MaybeT = Option; + // ... +} +``` + +Or this: + +```compile_fail,E0401 +fn foo(x: T) { + struct Foo { + x: T, + } + // ... +} +``` + +Items inside functions are basically just like top-level items, except +that they can only be used from the function they are in. + +There are a couple of solutions for this. + +If the item is a function, you may use a closure: + +``` +fn foo(x: T) { + let bar = |y: T| { // explicit type annotation may not be necessary + // .. + }; + bar(x); +} +``` + +For a generic item, you can copy over the parameters: + +``` +fn foo(x: T) { + fn bar(y: T) { + // .. + } + bar(x); +} +``` + +``` +fn foo(x: T) { + type MaybeT = Option; +} +``` + +Be sure to copy over any bounds as well: + +``` +fn foo(x: T) { + fn bar(y: T) { + // .. + } + bar(x); +} +``` + +``` +fn foo(x: T) { + struct Foo { + x: T, + } +} +``` + +This may require additional type hints in the function body. + +In case the item is a function inside an `impl`, defining a private helper +function might be easier: + +``` +# struct Foo(T); +impl Foo { + pub fn foo(&self, x: T) { + self.bar(x); + } + + fn bar(&self, y: T) { + // .. + } +} +``` + +For default impls in traits, the private helper solution won't work, however +closures or copying the parameters should still work. diff --git a/src/librustc_error_codes/error_codes/E0403.md b/src/librustc_error_codes/error_codes/E0403.md new file mode 100644 index 0000000000..5f4a40ce92 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0403.md @@ -0,0 +1,25 @@ +Some type parameters have the same name. + +Erroneous code example: + +```compile_fail,E0403 +fn f(s: T, u: T) {} // error: the name `T` is already used for a generic + // parameter in this item's generic parameters +``` + +Please verify that none of the type parameters are misspelled, and rename any +clashing parameters. Example: + +``` +fn f(s: T, u: Y) {} // ok! +``` + +Type parameters in an associated item also cannot shadow parameters from the +containing item: + +```compile_fail,E0403 +trait Foo { + fn do_something(&self) -> T; + fn do_something_else(&self, bar: T); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0404.md b/src/librustc_error_codes/error_codes/E0404.md new file mode 100644 index 0000000000..201107c05a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0404.md @@ -0,0 +1,43 @@ +You tried to use something which is not a trait in a trait position, such as +a bound or `impl`. + +Erroneous code example: + +```compile_fail,E0404 +struct Foo; +struct Bar; + +impl Foo for Bar {} // error: `Foo` is not a trait +``` + +Another erroneous code example: + +```compile_fail,E0404 +struct Foo; + +fn bar(t: T) {} // error: `Foo` is not a trait +``` + +Please verify that you didn't misspell the trait's name or otherwise use the +wrong identifier. Example: + +``` +trait Foo { + // some functions +} +struct Bar; + +impl Foo for Bar { // ok! + // functions implementation +} +``` + +or + +``` +trait Foo { + // some functions +} + +fn bar(t: T) {} // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0405.md b/src/librustc_error_codes/error_codes/E0405.md new file mode 100644 index 0000000000..ff1e8c0be8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0405.md @@ -0,0 +1,29 @@ +The code refers to a trait that is not in scope. + +Erroneous code example: + +```compile_fail,E0405 +struct Foo; + +impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope +``` + +Please verify that the name of the trait wasn't misspelled and ensure that it +was imported. Example: + +``` +# #[cfg(for_demonstration_only)] +// solution 1: +use some_file::SomeTrait; + +// solution 2: +trait SomeTrait { + // some functions +} + +struct Foo; + +impl SomeTrait for Foo { // ok! + // implements functions +} +``` diff --git a/src/librustc_error_codes/error_codes/E0407.md b/src/librustc_error_codes/error_codes/E0407.md new file mode 100644 index 0000000000..fa26c77a1b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0407.md @@ -0,0 +1,52 @@ +A definition of a method not in the implemented trait was given in a trait +implementation. + +Erroneous code example: + +```compile_fail,E0407 +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} // error: method `b` is not a member of trait `Foo` +} +``` + +Please verify you didn't misspell the method name and you used the correct +trait. First example: + +``` +trait Foo { + fn a(); + fn b(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} // ok! +} +``` + +Second example: + +``` +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} +} + +impl Bar { + fn b() {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0408.md b/src/librustc_error_codes/error_codes/E0408.md new file mode 100644 index 0000000000..3acdbb740a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0408.md @@ -0,0 +1,41 @@ +An "or" pattern was used where the variable bindings are not consistently bound +across patterns. + +Erroneous code example: + +```compile_fail,E0408 +match x { + Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is + // not bound in pattern #2 + _ => () +} +``` + +Here, `y` is bound to the contents of the `Some` and can be used within the +block corresponding to the match arm. However, in case `x` is `None`, we have +not specified what `y` is, and the block will use a nonexistent variable. + +To fix this error, either split into multiple match arms: + +``` +let x = Some(1); +match x { + Some(y) => { /* use y */ } + None => { /* ... */ } +} +``` + +or, bind the variable to a field of the same type in all sub-patterns of the +or pattern: + +``` +let x = (0, 2); +match x { + (0, y) | (y, 0) => { /* use y */} + _ => {} +} +``` + +In this example, if `x` matches the pattern `(0, _)`, the second field is set +to `y`. If it matches `(_, 0)`, the first field is set to `y`; so in all +cases `y` is set to some value. diff --git a/src/librustc_error_codes/error_codes/E0409.md b/src/librustc_error_codes/error_codes/E0409.md new file mode 100644 index 0000000000..53eb0fd057 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0409.md @@ -0,0 +1,38 @@ +An "or" pattern was used where the variable bindings are not consistently bound +across patterns. + +Erroneous code example: + +```compile_fail,E0409 +let x = (0, 2); +match x { + (0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with + // different mode in pattern #2 + // than in pattern #1 + _ => () +} +``` + +Here, `y` is bound by-value in one case and by-reference in the other. + +To fix this error, just use the same mode in both cases. +Generally using `ref` or `ref mut` where not already used will fix this: + +``` +let x = (0, 2); +match x { + (0, ref y) | (ref y, 0) => { /* use y */} + _ => () +} +``` + +Alternatively, split the pattern: + +``` +let x = (0, 2); +match x { + (y, 0) => { /* use y */ } + (0, ref y) => { /* use y */} + _ => () +} +``` diff --git a/src/librustc_error_codes/error_codes/E0411.md b/src/librustc_error_codes/error_codes/E0411.md new file mode 100644 index 0000000000..d82171533a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0411.md @@ -0,0 +1,56 @@ +The `Self` keyword was used outside an impl, trait, or type definition. + +Erroneous code example: + +```compile_fail,E0411 +::foo; // error: use of `Self` outside of an impl, trait, or type + // definition +``` + +The `Self` keyword represents the current type, which explains why it can only +be used inside an impl, trait, or type definition. It gives access to the +associated items of a type: + +``` +trait Foo { + type Bar; +} + +trait Baz : Foo { + fn bar() -> Self::Bar; // like this +} +``` + +However, be careful when two types have a common associated type: + +```compile_fail +trait Foo { + type Bar; +} + +trait Foo2 { + type Bar; +} + +trait Baz : Foo + Foo2 { + fn bar() -> Self::Bar; + // error: ambiguous associated type `Bar` in bounds of `Self` +} +``` + +This problem can be solved by specifying from which trait we want to use the +`Bar` type: + +``` +trait Foo { + type Bar; +} + +trait Foo2 { + type Bar; +} + +trait Baz : Foo + Foo2 { + fn bar() -> ::Bar; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0412.md b/src/librustc_error_codes/error_codes/E0412.md new file mode 100644 index 0000000000..60a09610d8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0412.md @@ -0,0 +1,64 @@ +The type name used is not in scope. + +Erroneous code examples: + +```compile_fail,E0412 +impl Something {} // error: type name `Something` is not in scope + +// or: + +trait Foo { + fn bar(N); // error: type name `N` is not in scope +} + +// or: + +fn foo(x: T) {} // type name `T` is not in scope +``` + +To fix this error, please verify you didn't misspell the type name, you did +declare it or imported it into the scope. Examples: + +``` +struct Something; + +impl Something {} // ok! + +// or: + +trait Foo { + type N; + + fn bar(_: Self::N); // ok! +} + +// or: + +fn foo(x: T) {} // ok! +``` + +Another case that causes this error is when a type is imported into a parent +module. To fix this, you can follow the suggestion and use File directly or +`use super::File;` which will import the types from the parent namespace. An +example that causes this error is below: + +```compile_fail,E0412 +use std::fs::File; + +mod foo { + fn some_function(f: File) {} +} +``` + +``` +use std::fs::File; + +mod foo { + // either + use super::File; + // or + // use std::fs::File; + fn foo(f: File) {} +} +# fn main() {} // don't insert it for us; that'll break imports +``` diff --git a/src/librustc_error_codes/error_codes/E0415.md b/src/librustc_error_codes/error_codes/E0415.md new file mode 100644 index 0000000000..97d733a7b2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0415.md @@ -0,0 +1,14 @@ +More than one function parameter have the same name. + +Erroneous code example: + +```compile_fail,E0415 +fn foo(f: i32, f: i32) {} // error: identifier `f` is bound more than + // once in this parameter list +``` + +Please verify you didn't misspell parameters' name. Example: + +``` +fn foo(f: i32, g: i32) {} // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0416.md b/src/librustc_error_codes/error_codes/E0416.md new file mode 100644 index 0000000000..7bc316dafc --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0416.md @@ -0,0 +1,28 @@ +An identifier is bound more than once in a pattern. + +Erroneous code example: + +```compile_fail,E0416 +match (1, 2) { + (x, x) => {} // error: identifier `x` is bound more than once in the + // same pattern +} +``` + +Please verify you didn't misspell identifiers' name. Example: + +``` +match (1, 2) { + (x, y) => {} // ok! +} +``` + +Or maybe did you mean to unify? Consider using a guard: + +``` +# let (A, B, C) = (1, 2, 3); +match (A, B, C) { + (x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ } + (y, z, see) => { /* A and B unequal; do another thing */ } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0422.md b/src/librustc_error_codes/error_codes/E0422.md new file mode 100644 index 0000000000..a91ea6a9e2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0422.md @@ -0,0 +1,21 @@ +You are trying to use an identifier that is either undefined or not a struct. +Erroneous code example: + +```compile_fail,E0422 +fn main () { + let x = Foo { x: 1, y: 2 }; +} +``` + +In this case, `Foo` is undefined, so it inherently isn't anything, and +definitely not a struct. + +```compile_fail +fn main () { + let foo = 1; + let x = foo { x: 1, y: 2 }; +} +``` + +In this case, `foo` is defined, but is not a struct, so Rust can't use it as +one. diff --git a/src/librustc_error_codes/error_codes/E0423.md b/src/librustc_error_codes/error_codes/E0423.md new file mode 100644 index 0000000000..6a7c31f5e0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0423.md @@ -0,0 +1,47 @@ +An identifier was used like a function name or a value was expected and the +identifier exists but it belongs to a different namespace. + +For (an erroneous) example, here a `struct` variant name were used as a +function: + +```compile_fail,E0423 +struct Foo { a: bool }; + +let f = Foo(); +// error: expected function, tuple struct or tuple variant, found `Foo` +// `Foo` is a struct name, but this expression uses it like a function name +``` + +Please verify you didn't misspell the name of what you actually wanted to use +here. Example: + +``` +fn Foo() -> u32 { 0 } + +let f = Foo(); // ok! +``` + +It is common to forget the trailing `!` on macro invocations, which would also +yield this error: + +```compile_fail,E0423 +println(""); +// error: expected function, tuple struct or tuple variant, +// found macro `println` +// did you mean `println!(...)`? (notice the trailing `!`) +``` + +Another case where this error is emitted is when a value is expected, but +something else is found: + +```compile_fail,E0423 +pub mod a { + pub const I: i32 = 1; +} + +fn h1() -> i32 { + a.I + //~^ ERROR expected value, found module `a` + // did you mean `a::I`? +} +``` diff --git a/src/librustc_error_codes/error_codes/E0424.md b/src/librustc_error_codes/error_codes/E0424.md new file mode 100644 index 0000000000..a9f6f579b4 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0424.md @@ -0,0 +1,40 @@ +The `self` keyword was used inside of an associated function without a "`self` +receiver" parameter. + +Erroneous code example: + +```compile_fail,E0424 +struct Foo; + +impl Foo { + // `bar` is a method, because it has a receiver parameter. + fn bar(&self) {} + + // `foo` is not a method, because it has no receiver parameter. + fn foo() { + self.bar(); // error: `self` value is a keyword only available in + // methods with a `self` parameter + } +} +``` + +The `self` keyword can only be used inside methods, which are associated +functions (functions defined inside of a `trait` or `impl` block) that have a +`self` receiver as its first parameter, like `self`, `&self`, `&mut self` or +`self: &mut Pin` (this last one is an example of an ["abitrary `self` +type"](https://github.com/rust-lang/rust/issues/44874)). + +Check if the associated function's parameter list should have contained a `self` +receiver for it to be a method, and add it if so. Example: + +``` +struct Foo; + +impl Foo { + fn bar(&self) {} + + fn foo(self) { // `foo` is now a method. + self.bar(); // ok! + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0425.md b/src/librustc_error_codes/error_codes/E0425.md new file mode 100644 index 0000000000..13e71b8506 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0425.md @@ -0,0 +1,60 @@ +An unresolved name was used. + +Erroneous code examples: + +```compile_fail,E0425 +something_that_doesnt_exist::foo; +// error: unresolved name `something_that_doesnt_exist::foo` + +// or: + +trait Foo { + fn bar() { + Self; // error: unresolved name `Self` + } +} + +// or: + +let x = unknown_variable; // error: unresolved name `unknown_variable` +``` + +Please verify that the name wasn't misspelled and ensure that the +identifier being referred to is valid for the given situation. Example: + +``` +enum something_that_does_exist { + Foo, +} +``` + +Or: + +``` +mod something_that_does_exist { + pub static foo : i32 = 0i32; +} + +something_that_does_exist::foo; // ok! +``` + +Or: + +``` +let unknown_variable = 12u32; +let x = unknown_variable; // ok! +``` + +If the item is not defined in the current module, it must be imported using a +`use` statement, like so: + +``` +# mod foo { pub fn bar() {} } +# fn main() { +use foo::bar; +bar(); +# } +``` + +If the item you are importing is not defined in some super-module of the +current module, then it must also be declared as public (e.g., `pub fn`). diff --git a/src/librustc_error_codes/error_codes/E0426.md b/src/librustc_error_codes/error_codes/E0426.md new file mode 100644 index 0000000000..15e7fb0473 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0426.md @@ -0,0 +1,17 @@ +An undeclared label was used. + +Erroneous code example: + +```compile_fail,E0426 +loop { + break 'a; // error: use of undeclared label `'a` +} +``` + +Please verify you spelt or declare the label correctly. Example: + +``` +'a: loop { + break 'a; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0428.md b/src/librustc_error_codes/error_codes/E0428.md new file mode 100644 index 0000000000..38db0b4bcf --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0428.md @@ -0,0 +1,16 @@ +A type or module has been defined more than once. + +Erroneous code example: + +```compile_fail,E0428 +struct Bar; +struct Bar; // error: duplicate definition of value `Bar` +``` + +Please verify you didn't misspell the type/module's name or remove/rename the +duplicated one. Example: + +``` +struct Bar; +struct Bar2; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0429.md b/src/librustc_error_codes/error_codes/E0429.md new file mode 100644 index 0000000000..8c5fd8624f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0429.md @@ -0,0 +1,21 @@ +The `self` keyword cannot appear alone as the last segment in a `use` +declaration. + +Erroneous code example: + +```compile_fail,E0429 +use std::fmt::self; // error: `self` imports are only allowed within a { } list +``` + +To use a namespace itself in addition to some of its members, `self` may appear +as part of a brace-enclosed list of imports: + +``` +use std::fmt::{self, Debug}; +``` + +If you only want to import the namespace, do so directly: + +``` +use std::fmt; +``` diff --git a/src/librustc_error_codes/error_codes/E0430.md b/src/librustc_error_codes/error_codes/E0430.md new file mode 100644 index 0000000000..8cca0f21e5 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0430.md @@ -0,0 +1,18 @@ +The `self` import appears more than once in the list. + +Erroneous code example: + +```compile_fail,E0430 +use something::{self, self}; // error: `self` import can only appear once in + // the list +``` + +Please verify you didn't misspell the import name or remove the duplicated +`self` import. Example: + +``` +# mod something {} +# fn main() { +use something::{self}; // ok! +# } +``` diff --git a/src/librustc_error_codes/error_codes/E0431.md b/src/librustc_error_codes/error_codes/E0431.md new file mode 100644 index 0000000000..1b70f5f1d7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0431.md @@ -0,0 +1,11 @@ +An invalid `self` import was made. + +Erroneous code example: + +```compile_fail,E0431 +use {self}; // error: `self` import can only appear in an import list with a + // non-empty prefix +``` + +You cannot import the current module into itself, please remove this import +or verify you didn't misspell it. diff --git a/src/librustc_error_codes/error_codes/E0432.md b/src/librustc_error_codes/error_codes/E0432.md new file mode 100644 index 0000000000..b562a85b78 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0432.md @@ -0,0 +1,32 @@ +An import was unresolved. + +Erroneous code example: + +```compile_fail,E0432 +use something::Foo; // error: unresolved import `something::Foo`. +``` + +Paths in `use` statements are relative to the crate root. To import items +relative to the current and parent modules, use the `self::` and `super::` +prefixes, respectively. Also verify that you didn't misspell the import +name and that the import exists in the module from where you tried to +import it. Example: + +``` +use self::something::Foo; // ok! + +mod something { + pub struct Foo; +} +# fn main() {} +``` + +Or, if you tried to use a module from an external crate, you may have missed +the `extern crate` declaration (which is usually placed in the crate root): + +``` +extern crate core; // Required to use the `core` crate + +use core::any; +# fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0433.md b/src/librustc_error_codes/error_codes/E0433.md new file mode 100644 index 0000000000..f9e333e8cc --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0433.md @@ -0,0 +1,17 @@ +An undeclared type or module was used. + +Erroneous code example: + +```compile_fail,E0433 +let map = HashMap::new(); +// error: failed to resolve: use of undeclared type or module `HashMap` +``` + +Please verify you didn't misspell the type/module's name or that you didn't +forget to import it: + + +``` +use std::collections::HashMap; // HashMap has been imported. +let map: HashMap = HashMap::new(); // So it can be used! +``` diff --git a/src/librustc_error_codes/error_codes/E0434.md b/src/librustc_error_codes/error_codes/E0434.md new file mode 100644 index 0000000000..e093f0796d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0434.md @@ -0,0 +1,42 @@ +This error indicates that a variable usage inside an inner function is invalid +because the variable comes from a dynamic environment. Inner functions do not +have access to their containing environment. + +Erroneous code example: + +```compile_fail,E0434 +fn foo() { + let y = 5; + fn bar() -> u32 { + y // error: can't capture dynamic environment in a fn item; use the + // || { ... } closure form instead. + } +} +``` + +Functions do not capture local variables. To fix this error, you can replace the +function with a closure: + +``` +fn foo() { + let y = 5; + let bar = || { + y + }; +} +``` + +or replace the captured variable with a constant or a static item: + +``` +fn foo() { + static mut X: u32 = 4; + const Y: u32 = 5; + fn bar() -> u32 { + unsafe { + X = 3; + } + Y + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0435.md b/src/librustc_error_codes/error_codes/E0435.md new file mode 100644 index 0000000000..424e5ce1e2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0435.md @@ -0,0 +1,21 @@ +A non-constant value was used in a constant expression. + +Erroneous code example: + +```compile_fail,E0435 +let foo = 42; +let a: [u8; foo]; // error: attempt to use a non-constant value in a constant +``` + +To fix this error, please replace the value with a constant. Example: + +``` +let a: [u8; 42]; // ok! +``` + +Or: + +``` +const FOO: usize = 42; +let a: [u8; FOO]; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0436.md b/src/librustc_error_codes/error_codes/E0436.md new file mode 100644 index 0000000000..b1afd9e960 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0436.md @@ -0,0 +1,47 @@ +The functional record update syntax is only allowed for structs. (Struct-like +enum variants don't qualify, for example.) + +Erroneous code example: + +```compile_fail,E0436 +enum PublicationFrequency { + Weekly, + SemiMonthly { days: (u8, u8), annual_special: bool }, +} + +fn one_up_competitor(competitor_frequency: PublicationFrequency) + -> PublicationFrequency { + match competitor_frequency { + PublicationFrequency::Weekly => PublicationFrequency::SemiMonthly { + days: (1, 15), annual_special: false + }, + c @ PublicationFrequency::SemiMonthly{ .. } => + PublicationFrequency::SemiMonthly { + annual_special: true, ..c // error: functional record update + // syntax requires a struct + } + } +} +``` + +Rewrite the expression without functional record update syntax: + +``` +enum PublicationFrequency { + Weekly, + SemiMonthly { days: (u8, u8), annual_special: bool }, +} + +fn one_up_competitor(competitor_frequency: PublicationFrequency) + -> PublicationFrequency { + match competitor_frequency { + PublicationFrequency::Weekly => PublicationFrequency::SemiMonthly { + days: (1, 15), annual_special: false + }, + PublicationFrequency::SemiMonthly{ days, .. } => + PublicationFrequency::SemiMonthly { + days, annual_special: true // ok! + } + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0437.md b/src/librustc_error_codes/error_codes/E0437.md new file mode 100644 index 0000000000..834cf33dbc --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0437.md @@ -0,0 +1,22 @@ +Trait implementations can only implement associated types that are members of +the trait in question. This error indicates that you attempted to implement +an associated type whose name does not match the name of any associated type +in the trait. + +Erroneous code example: + +```compile_fail,E0437 +trait Foo {} + +impl Foo for i32 { + type Bar = bool; +} +``` + +The solution to this problem is to remove the extraneous associated type: + +``` +trait Foo {} + +impl Foo for i32 {} +``` diff --git a/src/librustc_error_codes/error_codes/E0438.md b/src/librustc_error_codes/error_codes/E0438.md new file mode 100644 index 0000000000..cb141a5d24 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0438.md @@ -0,0 +1,22 @@ +Trait implementations can only implement associated constants that are +members of the trait in question. This error indicates that you +attempted to implement an associated constant whose name does not +match the name of any associated constant in the trait. + +Erroneous code example: + +```compile_fail,E0438 +trait Foo {} + +impl Foo for i32 { + const BAR: bool = true; +} +``` + +The solution to this problem is to remove the extraneous associated constant: + +``` +trait Foo {} + +impl Foo for i32 {} +``` diff --git a/src/librustc_error_codes/error_codes/E0439.md b/src/librustc_error_codes/error_codes/E0439.md new file mode 100644 index 0000000000..e6da2117ac --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0439.md @@ -0,0 +1,22 @@ +The length of the platform-intrinsic function `simd_shuffle` +wasn't specified. Erroneous code example: + +```compile_fail,E0439 +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; + // error: invalid `simd_shuffle`, needs length: `simd_shuffle` +} +``` + +The `simd_shuffle` function needs the length of the array passed as +last parameter in its name. Example: + +``` +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle8(a: A, b: A, c: [u32; 8]) -> B; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0445.md b/src/librustc_error_codes/error_codes/E0445.md new file mode 100644 index 0000000000..9cc62b2ba6 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0445.md @@ -0,0 +1,29 @@ +A private trait was used on a public type parameter bound. + +Erroneous code examples: + +```compile_fail,E0445 +#![deny(private_in_public)] + +trait Foo { + fn dummy(&self) { } +} + +pub trait Bar : Foo {} // error: private trait in public interface +pub struct Bar2(pub T); // same error +pub fn foo (t: T) {} // same error +``` + +To solve this error, please ensure that the trait is also public. The trait +can be made inaccessible if necessary by placing it into a private inner +module, but it still has to be marked with `pub`. Example: + +``` +pub trait Foo { // we set the Foo trait public + fn dummy(&self) { } +} + +pub trait Bar : Foo {} // ok! +pub struct Bar2(pub T); // ok! +pub fn foo (t: T) {} // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0446.md b/src/librustc_error_codes/error_codes/E0446.md new file mode 100644 index 0000000000..d0144478db --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0446.md @@ -0,0 +1,30 @@ +A private type was used in a public type signature. + +Erroneous code example: + +```compile_fail,E0446 +#![deny(private_in_public)] + +mod Foo { + struct Bar(u32); + + pub fn bar() -> Bar { // error: private type in public interface + Bar(0) + } +} +``` + +To solve this error, please ensure that the type is also public. The type +can be made inaccessible if necessary by placing it into a private inner +module, but it still has to be marked with `pub`. +Example: + +``` +mod Foo { + pub struct Bar(u32); // we set the Bar type public + + pub fn bar() -> Bar { // ok! + Bar(0) + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0447.md b/src/librustc_error_codes/error_codes/E0447.md new file mode 100644 index 0000000000..af8cd8d6d5 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0447.md @@ -0,0 +1,15 @@ +#### Note: this error code is no longer emitted by the compiler. + +The `pub` keyword was used inside a function. + +Erroneous code example: + +``` +fn foo() { + pub struct Bar; // error: visibility has no effect inside functions +} +``` + +Since we cannot access items defined inside a function, the visibility of its +items does not impact outer code. So using the `pub` keyword in this context +is invalid. diff --git a/src/librustc_error_codes/error_codes/E0448.md b/src/librustc_error_codes/error_codes/E0448.md new file mode 100644 index 0000000000..ba096f9e98 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0448.md @@ -0,0 +1,28 @@ +#### Note: this error code is no longer emitted by the compiler. + +The `pub` keyword was used inside a public enum. + +Erroneous code example: + +```compile_fail +pub enum Foo { + pub Bar, // error: unnecessary `pub` visibility +} +``` + +Since the enum is already public, adding `pub` on one its elements is +unnecessary. Example: + +```compile_fail +enum Foo { + pub Bar, // not ok! +} +``` + +This is the correct syntax: + +``` +pub enum Foo { + Bar, // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0449.md b/src/librustc_error_codes/error_codes/E0449.md new file mode 100644 index 0000000000..a3eb51961d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0449.md @@ -0,0 +1,37 @@ +A visibility qualifier was used when it was unnecessary. Erroneous code +examples: + +```compile_fail,E0449 +struct Bar; + +trait Foo { + fn foo(); +} + +pub impl Bar {} // error: unnecessary visibility qualifier + +pub impl Foo for Bar { // error: unnecessary visibility qualifier + pub fn foo() {} // error: unnecessary visibility qualifier +} +``` + +To fix this error, please remove the visibility qualifier when it is not +required. Example: + +``` +struct Bar; + +trait Foo { + fn foo(); +} + +// Directly implemented methods share the visibility of the type itself, +// so `pub` is unnecessary here +impl Bar {} + +// Trait methods share the visibility of the trait, so `pub` is +// unnecessary in either case +impl Foo for Bar { + fn foo() {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0451.md b/src/librustc_error_codes/error_codes/E0451.md new file mode 100644 index 0000000000..821073fe16 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0451.md @@ -0,0 +1,48 @@ +A struct constructor with private fields was invoked. + +Erroneous code example: + +```compile_fail,E0451 +mod Bar { + pub struct Foo { + pub a: isize, + b: isize, + } +} + +let f = Bar::Foo{ a: 0, b: 0 }; // error: field `b` of struct `Bar::Foo` + // is private +``` + +To fix this error, please ensure that all the fields of the struct are public, +or implement a function for easy instantiation. Examples: + +``` +mod Bar { + pub struct Foo { + pub a: isize, + pub b: isize, // we set `b` field public + } +} + +let f = Bar::Foo{ a: 0, b: 0 }; // ok! +``` + +Or: + +``` +mod Bar { + pub struct Foo { + pub a: isize, + b: isize, // still private + } + + impl Foo { + pub fn new() -> Foo { // we create a method to instantiate `Foo` + Foo { a: 0, b: 0 } + } + } +} + +let f = Bar::Foo::new(); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0452.md b/src/librustc_error_codes/error_codes/E0452.md new file mode 100644 index 0000000000..be3d573e10 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0452.md @@ -0,0 +1,14 @@ +An invalid lint attribute has been given. Erroneous code example: + +```compile_fail,E0452 +#![allow(foo = "")] // error: malformed lint attribute +``` + +Lint attributes only accept a list of identifiers (where each identifier is a +lint name). Ensure the attribute is of this form: + +``` +#![allow(foo)] // ok! +// or: +#![allow(foo, foo2)] // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0453.md b/src/librustc_error_codes/error_codes/E0453.md new file mode 100644 index 0000000000..11789db8f3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0453.md @@ -0,0 +1,42 @@ +A lint check attribute was overruled by a `forbid` directive set as an +attribute on an enclosing scope, or on the command line with the `-F` option. + +Example of erroneous code: + +```compile_fail,E0453 +#![forbid(non_snake_case)] + +#[allow(non_snake_case)] +fn main() { + let MyNumber = 2; // error: allow(non_snake_case) overruled by outer + // forbid(non_snake_case) +} +``` + +The `forbid` lint setting, like `deny`, turns the corresponding compiler +warning into a hard error. Unlike `deny`, `forbid` prevents itself from being +overridden by inner attributes. + +If you're sure you want to override the lint check, you can change `forbid` to +`deny` (or use `-D` instead of `-F` if the `forbid` setting was given as a +command-line option) to allow the inner lint check attribute: + +``` +#![deny(non_snake_case)] + +#[allow(non_snake_case)] +fn main() { + let MyNumber = 2; // ok! +} +``` + +Otherwise, edit the code to pass the lint check, and remove the overruled +attribute: + +``` +#![forbid(non_snake_case)] + +fn main() { + let my_number = 2; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0454.md b/src/librustc_error_codes/error_codes/E0454.md new file mode 100644 index 0000000000..d331488508 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0454.md @@ -0,0 +1,13 @@ +A link name was given with an empty name. Erroneous code example: + +```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-codegen) +#[link(name = "")] extern {} +// error: `#[link(name = "")]` given with empty name +``` + +The rust compiler cannot link to an external library if you don't give it its +name. Example: + +```no_run +#[link(name = "some_lib")] extern {} // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0455.md b/src/librustc_error_codes/error_codes/E0455.md new file mode 100644 index 0000000000..a642528dee --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0455.md @@ -0,0 +1,19 @@ +Linking with `kind=framework` is only supported when targeting macOS, +as frameworks are specific to that operating system. + +Erroneous code example: + +```ignore (should-compile_fail-but-cannot-doctest-conditionally-without-macos) +#[link(name = "FooCoreServices", kind = "framework")] extern {} +// OS used to compile is Linux for example +``` + +To solve this error you can use conditional compilation: + +``` +#[cfg_attr(target="macos", link(name = "FooCoreServices", kind = "framework"))] +extern {} +``` + +See more: +https://doc.rust-lang.org/reference/attributes.html#conditional-compilation diff --git a/src/librustc_error_codes/error_codes/E0458.md b/src/librustc_error_codes/error_codes/E0458.md new file mode 100644 index 0000000000..385079d403 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0458.md @@ -0,0 +1,12 @@ +An unknown "kind" was specified for a link attribute. Erroneous code example: + +```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-codegen) +#[link(kind = "wonderful_unicorn")] extern {} +// error: unknown kind: `wonderful_unicorn` +``` + +Please specify a valid "kind" value, from one of the following: + +* static +* dylib +* framework diff --git a/src/librustc_error_codes/error_codes/E0459.md b/src/librustc_error_codes/error_codes/E0459.md new file mode 100644 index 0000000000..663bc322ee --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0459.md @@ -0,0 +1,13 @@ +A link was used without a name parameter. Erroneous code example: + +```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-codegen) +#[link(kind = "dylib")] extern {} +// error: `#[link(...)]` specified without `name = "foo"` +``` + +Please add the name parameter to allow the rust compiler to find the library +you want. Example: + +```no_run +#[link(kind = "dylib", name = "some_lib")] extern {} // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0463.md b/src/librustc_error_codes/error_codes/E0463.md new file mode 100644 index 0000000000..41add698cd --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0463.md @@ -0,0 +1,11 @@ +A plugin/crate was declared but cannot be found. Erroneous code example: + +```compile_fail,E0463 +#![feature(plugin)] +#![plugin(cookie_monster)] // error: can't find crate for `cookie_monster` +extern crate cake_is_a_lie; // error: can't find crate for `cake_is_a_lie` +``` + +You need to link your code to the relevant crate in order to be able to use it +(through Cargo or the `-L` option of rustc example). Plugins are crates as +well, and you link to them the same way. diff --git a/src/librustc_error_codes/error_codes/E0466.md b/src/librustc_error_codes/error_codes/E0466.md new file mode 100644 index 0000000000..443b7bae13 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0466.md @@ -0,0 +1,34 @@ +Macro import declarations were malformed. + +Erroneous code examples: + +```compile_fail,E0466 +#[macro_use(a_macro(another_macro))] // error: invalid import declaration +extern crate core as some_crate; + +#[macro_use(i_want = "some_macros")] // error: invalid import declaration +extern crate core as another_crate; +``` + +This is a syntax error at the level of attribute declarations. The proper +syntax for macro imports is the following: + +```ignore (cannot-doctest-multicrate-project) +// In some_crate: +#[macro_export] +macro_rules! get_tacos { + ... +} + +#[macro_export] +macro_rules! get_pimientos { + ... +} + +// In your crate: +#[macro_use(get_tacos, get_pimientos)] // It imports `get_tacos` and +extern crate some_crate; // `get_pimientos` macros from some_crate +``` + +If you would like to import all exported macros, write `macro_use` with no +arguments. diff --git a/src/librustc_error_codes/error_codes/E0468.md b/src/librustc_error_codes/error_codes/E0468.md new file mode 100644 index 0000000000..73e3ebb949 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0468.md @@ -0,0 +1,27 @@ +A non-root module attempts to import macros from another crate. + +Example of erroneous code: + +```compile_fail,E0468 +mod foo { + #[macro_use(debug_assert)] // error: must be at crate root to import + extern crate core; // macros from another crate + fn run_macro() { debug_assert!(true); } +} +``` + +Only `extern crate` imports at the crate root level are allowed to import +macros. + +Either move the macro import to crate root or do without the foreign macros. +This will work: + +``` +#[macro_use(debug_assert)] +extern crate core; + +mod foo { + fn run_macro() { debug_assert!(true); } +} +# fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0469.md b/src/librustc_error_codes/error_codes/E0469.md new file mode 100644 index 0000000000..22db976aac --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0469.md @@ -0,0 +1,39 @@ +A macro listed for import was not found. + +Erroneous code example: + +```compile_fail,E0469 +#[macro_use(drink, be_merry)] // error: imported macro not found +extern crate alloc; + +fn main() { + // ... +} +``` + +Either the listed macro is not contained in the imported crate, or it is not +exported from the given crate. + +This could be caused by a typo. Did you misspell the macro's name? + +Double-check the names of the macros listed for import, and that the crate +in question exports them. + +A working version would be: + +```ignore (cannot-doctest-multicrate-project) +// In some_crate crate: +#[macro_export] +macro_rules! eat { + ... +} + +#[macro_export] +macro_rules! drink { + ... +} + +// In your crate: +#[macro_use(eat, drink)] +extern crate some_crate; //ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0478.md b/src/librustc_error_codes/error_codes/E0478.md new file mode 100644 index 0000000000..4bc5fde2e8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0478.md @@ -0,0 +1,28 @@ +A lifetime bound was not satisfied. + +Erroneous code example: + +```compile_fail,E0478 +// Check that the explicit lifetime bound (`'SnowWhite`, in this example) must +// outlive all the superbounds from the trait (`'kiss`, in this example). + +trait Wedding<'t>: 't { } + +struct Prince<'kiss, 'SnowWhite> { + child: Box + 'SnowWhite>, + // error: lifetime bound not satisfied +} +``` + +In this example, the `'SnowWhite` lifetime is supposed to outlive the `'kiss` +lifetime but the declaration of the `Prince` struct doesn't enforce it. To fix +this issue, you need to specify it: + +``` +trait Wedding<'t>: 't { } + +struct Prince<'kiss, 'SnowWhite: 'kiss> { // You say here that 'SnowWhite + // must live longer than 'kiss. + child: Box + 'SnowWhite>, // And now it's all good! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0491.md b/src/librustc_error_codes/error_codes/E0491.md new file mode 100644 index 0000000000..1ccaf71257 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0491.md @@ -0,0 +1,32 @@ +A reference has a longer lifetime than the data it references. + +Erroneous code example: + +```compile_fail,E0491 +trait SomeTrait<'a> { + type Output; +} + +impl<'a, T> SomeTrait<'a> for T { + type Output = &'a T; // compile error E0491 +} +``` + +Here, the problem is that a reference type like `&'a T` is only valid +if all the data in T outlives the lifetime `'a`. But this impl as written +is applicable to any lifetime `'a` and any type `T` -- we have no guarantee +that `T` outlives `'a`. To fix this, you can add a where clause like +`where T: 'a`. + +``` +trait SomeTrait<'a> { + type Output; +} + +impl<'a, T> SomeTrait<'a> for T +where + T: 'a, +{ + type Output = &'a T; // compile error E0491 +} +``` diff --git a/src/librustc_error_codes/error_codes/E0492.md b/src/librustc_error_codes/error_codes/E0492.md new file mode 100644 index 0000000000..1caa59999a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0492.md @@ -0,0 +1,71 @@ +A borrow of a constant containing interior mutability was attempted. + +Erroneous code example: + +```compile_fail,E0492 +use std::sync::atomic::AtomicUsize; + +const A: AtomicUsize = AtomicUsize::new(0); +static B: &'static AtomicUsize = &A; +// error: cannot borrow a constant which may contain interior mutability, +// create a static instead +``` + +A `const` represents a constant value that should never change. If one takes +a `&` reference to the constant, then one is taking a pointer to some memory +location containing the value. Normally this is perfectly fine: most values +can't be changed via a shared `&` pointer, but interior mutability would allow +it. That is, a constant value could be mutated. On the other hand, a `static` is +explicitly a single memory location, which can be mutated at will. + +So, in order to solve this error, either use statics which are `Sync`: + +``` +use std::sync::atomic::AtomicUsize; + +static A: AtomicUsize = AtomicUsize::new(0); +static B: &'static AtomicUsize = &A; // ok! +``` + +You can also have this error while using a cell type: + +```compile_fail,E0492 +use std::cell::Cell; + +const A: Cell = Cell::new(1); +const B: &Cell = &A; +// error: cannot borrow a constant which may contain interior mutability, +// create a static instead + +// or: +struct C { a: Cell } + +const D: C = C { a: Cell::new(1) }; +const E: &Cell = &D.a; // error + +// or: +const F: &C = &D; // error +``` + +This is because cell types do operations that are not thread-safe. Due to this, +they don't implement Sync and thus can't be placed in statics. + +However, if you still wish to use these types, you can achieve this by an unsafe +wrapper: + +``` +use std::cell::Cell; +use std::marker::Sync; + +struct NotThreadSafe { + value: Cell, +} + +unsafe impl Sync for NotThreadSafe {} + +static A: NotThreadSafe = NotThreadSafe { value : Cell::new(1) }; +static B: &'static NotThreadSafe = &A; // ok! +``` + +Remember this solution is unsafe! You will have to ensure that accesses to the +cell are synchronized. diff --git a/src/librustc_error_codes/error_codes/E0493.md b/src/librustc_error_codes/error_codes/E0493.md new file mode 100644 index 0000000000..90a0cbce62 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0493.md @@ -0,0 +1,42 @@ +A type with a `Drop` implementation was destructured when trying to initialize +a static item. + +Erroneous code example: + +```compile_fail,E0493 +enum DropType { + A, +} + +impl Drop for DropType { + fn drop(&mut self) {} +} + +struct Foo { + field1: DropType, +} + +static FOO: Foo = Foo { ..Foo { field1: DropType::A } }; // error! +``` + +The problem here is that if the given type or one of its fields implements the +`Drop` trait, this `Drop` implementation cannot be called during the static +type initialization which might cause a memory leak. To prevent this issue, +you need to instantiate all the static type's fields by hand. + +``` +enum DropType { + A, +} + +impl Drop for DropType { + fn drop(&mut self) {} +} + +struct Foo { + field1: DropType, +} + +static FOO: Foo = Foo { field1: DropType::A }; // We initialize all fields + // by hand. +``` diff --git a/src/librustc_error_codes/error_codes/E0495.md b/src/librustc_error_codes/error_codes/E0495.md new file mode 100644 index 0000000000..f956237b80 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0495.md @@ -0,0 +1,38 @@ +A lifetime cannot be determined in the given situation. + +Erroneous code example: + +```compile_fail,E0495 +fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { + match (&t,) { // error! + ((u,),) => u, + } +} + +let y = Box::new((42,)); +let x = transmute_lifetime(&y); +``` + +In this code, you have two ways to solve this issue: + 1. Enforce that `'a` lives at least as long as `'b`. + 2. Use the same lifetime requirement for both input and output values. + +So for the first solution, you can do it by replacing `'a` with `'a: 'b`: + +``` +fn transmute_lifetime<'a: 'b, 'b, T>(t: &'a (T,)) -> &'b T { + match (&t,) { // ok! + ((u,),) => u, + } +} +``` + +In the second you can do it by simply removing `'b` so they both use `'a`: + +``` +fn transmute_lifetime<'a, T>(t: &'a (T,)) -> &'a T { + match (&t,) { // ok! + ((u,),) => u, + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0496.md b/src/librustc_error_codes/error_codes/E0496.md new file mode 100644 index 0000000000..83d65cd3e0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0496.md @@ -0,0 +1,31 @@ +A lifetime name is shadowing another lifetime name. + +Erroneous code example: + +```compile_fail,E0496 +struct Foo<'a> { + a: &'a i32, +} + +impl<'a> Foo<'a> { + fn f<'a>(x: &'a i32) { // error: lifetime name `'a` shadows a lifetime + // name that is already in scope + } +} +``` + +Please change the name of one of the lifetimes to remove this error. Example: + +``` +struct Foo<'a> { + a: &'a i32, +} + +impl<'a> Foo<'a> { + fn f<'b>(x: &'b i32) { // ok! + } +} + +fn main() { +} +``` diff --git a/src/librustc_error_codes/error_codes/E0497.md b/src/librustc_error_codes/error_codes/E0497.md new file mode 100644 index 0000000000..ef2882415d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0497.md @@ -0,0 +1,14 @@ +#### Note: this error code is no longer emitted by the compiler. + +A stability attribute was used outside of the standard library. + +Erroneous code example: + +```compile_fail +#[stable] // error: stability attributes may not be used outside of the + // standard library +fn foo() {} +``` + +It is not possible to use stability attributes outside of the standard library. +Also, for now, it is not possible to write deprecation messages either. diff --git a/src/librustc_error_codes/error_codes/E0499.md b/src/librustc_error_codes/error_codes/E0499.md new file mode 100644 index 0000000000..370ceef530 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0499.md @@ -0,0 +1,30 @@ +A variable was borrowed as mutable more than once. + +Erroneous code example: + +```compile_fail,E0499 +let mut i = 0; +let mut x = &mut i; +let mut a = &mut i; +x; +// error: cannot borrow `i` as mutable more than once at a time +``` + +Please note that in rust, you can either have many immutable references, or one +mutable reference. Take a look at +https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html for more +information. Example: + + +``` +let mut i = 0; +let mut x = &mut i; // ok! + +// or: +let mut i = 0; +let a = &i; // ok! +let b = &i; // still ok! +let c = &i; // still ok! +b; +a; +``` diff --git a/src/librustc_error_codes/error_codes/E0500.md b/src/librustc_error_codes/error_codes/E0500.md new file mode 100644 index 0000000000..fde31d2c74 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0500.md @@ -0,0 +1,41 @@ +A borrowed variable was used by a closure. + +Erroneous code example: + +```compile_fail,E0500 +fn you_know_nothing(jon_snow: &mut i32) { + let nights_watch = &jon_snow; + let starks = || { + *jon_snow = 3; // error: closure requires unique access to `jon_snow` + // but it is already borrowed + }; + println!("{}", nights_watch); +} +``` + +In here, `jon_snow` is already borrowed by the `nights_watch` reference, so it +cannot be borrowed by the `starks` closure at the same time. To fix this issue, +you can create the closure after the borrow has ended: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + let nights_watch = &jon_snow; + println!("{}", nights_watch); + let starks = || { + *jon_snow = 3; + }; +} +``` + +Or, if the type implements the `Clone` trait, you can clone it between +closures: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + let mut jon_copy = jon_snow.clone(); + let starks = || { + *jon_snow = 3; + }; + println!("{}", jon_copy); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0501.md b/src/librustc_error_codes/error_codes/E0501.md new file mode 100644 index 0000000000..95e0dfd400 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0501.md @@ -0,0 +1,76 @@ +This error indicates that a mutable variable is being used while it is still +captured by a closure. Because the closure has borrowed the variable, it is not +available for use until the closure goes out of scope. + +Note that a capture will either move or borrow a variable, but in this +situation, the closure is borrowing the variable. Take a look at +http://rustbyexample.com/fn/closures/capture.html for more information about +capturing. + +Erroneous code example: + +```compile_fail,E0501 +fn inside_closure(x: &mut i32) { + // Actions which require unique access +} + +fn outside_closure(x: &mut i32) { + // Actions which require unique access +} + +fn foo(a: &mut i32) { + let mut bar = || { + inside_closure(a) + }; + outside_closure(a); // error: cannot borrow `*a` as mutable because previous + // closure requires unique access. + bar(); +} +``` + +To fix this error, you can finish using the closure before using the captured +variable: + +``` +fn inside_closure(x: &mut i32) {} +fn outside_closure(x: &mut i32) {} + +fn foo(a: &mut i32) { + let mut bar = || { + inside_closure(a) + }; + bar(); + // borrow on `a` ends. + outside_closure(a); // ok! +} +``` + +Or you can pass the variable as a parameter to the closure: + +``` +fn inside_closure(x: &mut i32) {} +fn outside_closure(x: &mut i32) {} + +fn foo(a: &mut i32) { + let mut bar = |s: &mut i32| { + inside_closure(s) + }; + outside_closure(a); + bar(a); +} +``` + +It may be possible to define the closure later: + +``` +fn inside_closure(x: &mut i32) {} +fn outside_closure(x: &mut i32) {} + +fn foo(a: &mut i32) { + outside_closure(a); + let mut bar = || { + inside_closure(a) + }; + bar(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0502.md b/src/librustc_error_codes/error_codes/E0502.md new file mode 100644 index 0000000000..69220259e3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0502.md @@ -0,0 +1,29 @@ +This error indicates that you are trying to borrow a variable as mutable when it +has already been borrowed as immutable. + +Erroneous code example: + +```compile_fail,E0502 +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + let ref y = a; // a is borrowed as immutable. + bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed + // as immutable + println!("{}", y); +} +``` + +To fix this error, ensure that you don't have any other references to the +variable before trying to access it mutably: + +``` +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + bar(a); + let ref y = a; // ok! + println!("{}", y); +} +``` + +For more information on the rust ownership system, take a look at +https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html. diff --git a/src/librustc_error_codes/error_codes/E0503.md b/src/librustc_error_codes/error_codes/E0503.md new file mode 100644 index 0000000000..c683619e3d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0503.md @@ -0,0 +1,52 @@ +A value was used after it was mutably borrowed. + +Erroneous code example: + +```compile_fail,E0503 +fn main() { + let mut value = 3; + // Create a mutable borrow of `value`. + let borrow = &mut value; + let _sum = value + 1; // error: cannot use `value` because + // it was mutably borrowed + println!("{}", borrow); +} +``` + +In this example, `value` is mutably borrowed by `borrow` and cannot be +used to calculate `sum`. This is not possible because this would violate +Rust's mutability rules. + +You can fix this error by finishing using the borrow before the next use of +the value: + +``` +fn main() { + let mut value = 3; + let borrow = &mut value; + println!("{}", borrow); + // The block has ended and with it the borrow. + // You can now use `value` again. + let _sum = value + 1; +} +``` + +Or by cloning `value` before borrowing it: + +``` +fn main() { + let mut value = 3; + // We clone `value`, creating a copy. + let value_cloned = value.clone(); + // The mutable borrow is a reference to `value` and + // not to `value_cloned`... + let borrow = &mut value; + // ... which means we can still use `value_cloned`, + let _sum = value_cloned + 1; + // even though the borrow only ends here. + println!("{}", borrow); +} +``` + +You can find more information about borrowing in the rust-book: +http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html diff --git a/src/librustc_error_codes/error_codes/E0504.md b/src/librustc_error_codes/error_codes/E0504.md new file mode 100644 index 0000000000..bcbd00a869 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0504.md @@ -0,0 +1,103 @@ +#### Note: this error code is no longer emitted by the compiler. + +This error occurs when an attempt is made to move a borrowed variable into a +closure. + +Erroneous code example: + +```compile_fail +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { + println!("child function: {}", fancy_num.num); + // error: cannot move `fancy_num` into closure because it is borrowed + }; + + x(); + println!("main function: {}", fancy_ref.num); +} +``` + +Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into +the closure `x`. There is no way to move a value into a closure while it is +borrowed, as that would invalidate the borrow. + +If the closure can't outlive the value being moved, try using a reference +rather than moving: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { + // fancy_ref is usable here because it doesn't move `fancy_num` + println!("child function: {}", fancy_ref.num); + }; + + x(); + + println!("main function: {}", fancy_num.num); +} +``` + +If the value has to be borrowed and then moved, try limiting the lifetime of +the borrow using a scoped block: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + + { + let fancy_ref = &fancy_num; + println!("main function: {}", fancy_ref.num); + // `fancy_ref` goes out of scope here + } + + let x = move || { + // `fancy_num` can be moved now (no more references exist) + println!("child function: {}", fancy_num.num); + }; + + x(); +} +``` + +If the lifetime of a reference isn't enough, such as in the case of threading, +consider using an `Arc` to create a reference-counted value: + +``` +use std::sync::Arc; +use std::thread; + +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_ref1 = Arc::new(FancyNum { num: 5 }); + let fancy_ref2 = fancy_ref1.clone(); + + let x = thread::spawn(move || { + // `fancy_ref1` can be moved and has a `'static` lifetime + println!("child thread: {}", fancy_ref1.num); + }); + + x.join().expect("child thread should finish"); + println!("main thread: {}", fancy_ref2.num); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0505.md b/src/librustc_error_codes/error_codes/E0505.md new file mode 100644 index 0000000000..14baa01cb5 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0505.md @@ -0,0 +1,85 @@ +A value was moved out while it was still borrowed. + +Erroneous code example: + +```compile_fail,E0505 +struct Value {} + +fn borrow(val: &Value) {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + let _ref_to_val: &Value = &x; + eat(x); + borrow(_ref_to_val); +} +``` + +Here, the function `eat` takes ownership of `x`. However, +`x` cannot be moved because the borrow to `_ref_to_val` +needs to last till the function `borrow`. +To fix that you can do a few different things: + +* Try to avoid moving the variable. +* Release borrow before move. +* Implement the `Copy` trait on the type. + +Examples: + +``` +struct Value {} + +fn borrow(val: &Value) {} + +fn eat(val: &Value) {} + +fn main() { + let x = Value{}; + + let ref_to_val: &Value = &x; + eat(&x); // pass by reference, if it's possible + borrow(ref_to_val); +} +``` + +Or: + +``` +struct Value {} + +fn borrow(val: &Value) {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + + let ref_to_val: &Value = &x; + borrow(ref_to_val); + // ref_to_val is no longer used. + eat(x); +} +``` + +Or: + +``` +#[derive(Clone, Copy)] // implement Copy trait +struct Value {} + +fn borrow(val: &Value) {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + let ref_to_val: &Value = &x; + eat(x); // it will be copied here. + borrow(ref_to_val); +} +``` + +You can find more information about borrowing in the rust-book: +http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html diff --git a/src/librustc_error_codes/error_codes/E0506.md b/src/librustc_error_codes/error_codes/E0506.md new file mode 100644 index 0000000000..9b8e316487 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0506.md @@ -0,0 +1,81 @@ +This error occurs when an attempt is made to assign to a borrowed value. + +Erroneous code example: + +```compile_fail,E0506 +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + fancy_num = FancyNum { num: 6 }; + // error: cannot assign to `fancy_num` because it is borrowed + + println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); +} +``` + +Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't +be assigned to a new value as it would invalidate the reference. + +Alternatively, we can move out of `fancy_num` into a second `fancy_num`: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + let moved_num = fancy_num; + fancy_num = FancyNum { num: 6 }; + + println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num); +} +``` + +If the value has to be borrowed, try limiting the lifetime of the borrow using +a scoped block: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + + { + let fancy_ref = &fancy_num; + println!("Ref: {}", fancy_ref.num); + } + + // Works because `fancy_ref` is no longer in scope + fancy_num = FancyNum { num: 6 }; + println!("Num: {}", fancy_num.num); +} +``` + +Or by moving the reference into a function: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + + print_fancy_ref(&fancy_num); + + // Works because function borrow has ended + fancy_num = FancyNum { num: 6 }; + println!("Num: {}", fancy_num.num); +} + +fn print_fancy_ref(fancy_ref: &FancyNum){ + println!("Ref: {}", fancy_ref.num); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0507.md b/src/librustc_error_codes/error_codes/E0507.md new file mode 100644 index 0000000000..89a6fb4737 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0507.md @@ -0,0 +1,131 @@ +You tried to move out of a value which was borrowed. + +This can also happen when using a type implementing `Fn` or `FnMut`, as neither +allows moving out of them (they usually represent closures which can be called +more than once). Much of the text following applies equally well to non-`FnOnce` +closure bodies. + +Erroneous code example: + +```compile_fail,E0507 +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); // error: cannot move out of borrowed content +} +``` + +Here, the `nothing_is_true` method takes the ownership of `self`. However, +`self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, +which is a borrow of the content owned by the `RefCell`. To fix this error, +you have three choices: + +* Try to avoid moving the variable. +* Somehow reclaim the ownership. +* Implement the `Copy` trait on the type. + +Examples: + +``` +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(&self) {} // First case, we don't take ownership +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); // ok! +} +``` + +Or: + +``` +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + let x = x.into_inner(); // we get back ownership + + x.nothing_is_true(); // ok! +} +``` + +Or: + +``` +use std::cell::RefCell; + +#[derive(Clone, Copy)] // we implement the Copy trait +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); // ok! +} +``` + +Moving a member out of a mutably borrowed struct will also cause E0507 error: + +```compile_fail,E0507 +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +struct Batcave { + knight: TheDarkKnight +} + +fn main() { + let mut cave = Batcave { + knight: TheDarkKnight + }; + let borrowed = &mut cave; + + borrowed.knight.nothing_is_true(); // E0507 +} +``` + +It is fine only if you put something back. `mem::replace` can be used for that: + +``` +# struct TheDarkKnight; +# impl TheDarkKnight { fn nothing_is_true(self) {} } +# struct Batcave { knight: TheDarkKnight } +use std::mem; + +let mut cave = Batcave { + knight: TheDarkKnight +}; +let borrowed = &mut cave; + +mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! +``` + +You can find more information about borrowing in the rust-book: +http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html diff --git a/src/librustc_error_codes/error_codes/E0508.md b/src/librustc_error_codes/error_codes/E0508.md new file mode 100644 index 0000000000..33572fca6a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0508.md @@ -0,0 +1,41 @@ +A value was moved out of a non-copy fixed-size array. + +Erroneous code example: + +```compile_fail,E0508 +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + let _value = array[0]; // error: cannot move out of type `[NonCopy; 1]`, + // a non-copy fixed-size array +} +``` + +The first element was moved out of the array, but this is not +possible because `NonCopy` does not implement the `Copy` trait. + +Consider borrowing the element instead of moving it: + +``` +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + let _value = &array[0]; // Borrowing is allowed, unlike moving. +} +``` + +Alternatively, if your type implements `Clone` and you need to own the value, +consider borrowing and then cloning: + +``` +#[derive(Clone)] +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + // Now you can clone the array element. + let _value = array[0].clone(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0509.md b/src/librustc_error_codes/error_codes/E0509.md new file mode 100644 index 0000000000..9cbd7d695a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0509.md @@ -0,0 +1,92 @@ +This error occurs when an attempt is made to move out of a value whose type +implements the `Drop` trait. + +Erroneous code example: + +```compile_fail,E0509 +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + // Destruct DropStruct, possibly using FancyNum + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let fancy_field = drop_struct.fancy; // Error E0509 + println!("Fancy: {}", fancy_field.num); + // implicit call to `drop_struct.drop()` as drop_struct goes out of scope +} +``` + +Here, we tried to move a field out of a struct of type `DropStruct` which +implements the `Drop` trait. However, a struct cannot be dropped if one or +more of its fields have been moved. + +Structs implementing the `Drop` trait have an implicit destructor that gets +called when they go out of scope. This destructor may use the fields of the +struct, so moving out of the struct could make it impossible to run the +destructor. Therefore, we must think of all values whose type implements the +`Drop` trait as single units whose fields cannot be moved. + +This error can be fixed by creating a reference to the fields of a struct, +enum, or tuple using the `ref` keyword: + +``` +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + // Destruct DropStruct, possibly using FancyNum + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let ref fancy_field = drop_struct.fancy; // No more errors! + println!("Fancy: {}", fancy_field.num); + // implicit call to `drop_struct.drop()` as drop_struct goes out of scope +} +``` + +Note that this technique can also be used in the arms of a match expression: + +``` +struct FancyNum { + num: usize +} + +enum DropEnum { + Fancy(FancyNum) +} + +impl Drop for DropEnum { + fn drop(&mut self) { + // Destruct DropEnum, possibly using FancyNum + } +} + +fn main() { + // Creates and enum of type `DropEnum`, which implements `Drop` + let drop_enum = DropEnum::Fancy(FancyNum{num: 10}); + match drop_enum { + // Creates a reference to the inside of `DropEnum::Fancy` + DropEnum::Fancy(ref fancy_field) => // No error! + println!("It was fancy-- {}!", fancy_field.num), + } + // implicit call to `drop_enum.drop()` as drop_enum goes out of scope +} +``` diff --git a/src/librustc_error_codes/error_codes/E0510.md b/src/librustc_error_codes/error_codes/E0510.md new file mode 100644 index 0000000000..d5be417888 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0510.md @@ -0,0 +1,16 @@ +Cannot mutate place in this match guard. + +When matching on a variable it cannot be mutated in the match guards, as this +could cause the match to be non-exhaustive: + +```compile_fail,E0510 +let mut x = Some(0); +match x { + None => (), + Some(_) if { x = None; false } => (), + Some(v) => (), // No longer matches +} +``` + +Here executing `x = None` would modify the value being matched and require us +to go "back in time" to the `None` arm. diff --git a/src/librustc_error_codes/error_codes/E0511.md b/src/librustc_error_codes/error_codes/E0511.md new file mode 100644 index 0000000000..2d6ff8241e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0511.md @@ -0,0 +1,32 @@ +Invalid monomorphization of an intrinsic function was used. Erroneous code +example: + +```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +fn main() { + unsafe { simd_add(0, 1); } + // error: invalid monomorphization of `simd_add` intrinsic +} +``` + +The generic type has to be a SIMD type. Example: + +``` +#![feature(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x2(i32, i32); + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0512.md b/src/librustc_error_codes/error_codes/E0512.md new file mode 100644 index 0000000000..c13c0511c7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0512.md @@ -0,0 +1,24 @@ +Transmute with two differently sized types was attempted. Erroneous code +example: + +```compile_fail,E0512 +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0u16)); } + // error: cannot transmute between types of different sizes, + // or dependently-sized types +} +``` + +Please use types with same size or use the expected type directly. Example: + +``` +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! + // or: + unsafe { takes_u8(0u8); } // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0515.md b/src/librustc_error_codes/error_codes/E0515.md new file mode 100644 index 0000000000..9580b6f92a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0515.md @@ -0,0 +1,37 @@ +Cannot return value that references local variable + +Local variables, function parameters and temporaries are all dropped before the +end of the function body. So a reference to them cannot be returned. + +Erroneous code example: + +```compile_fail,E0515 +fn get_dangling_reference() -> &'static i32 { + let x = 0; + &x +} +``` + +```compile_fail,E0515 +use std::slice::Iter; +fn get_dangling_iterator<'a>() -> Iter<'a, i32> { + let v = vec![1, 2, 3]; + v.iter() +} +``` + +Consider returning an owned value instead: + +``` +use std::vec::IntoIter; + +fn get_integer() -> i32 { + let x = 0; + x +} + +fn get_owned_iterator() -> IntoIter { + let v = vec![1, 2, 3]; + v.into_iter() +} +``` diff --git a/src/librustc_error_codes/error_codes/E0516.md b/src/librustc_error_codes/error_codes/E0516.md new file mode 100644 index 0000000000..815d760901 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0516.md @@ -0,0 +1,16 @@ +The `typeof` keyword is currently reserved but unimplemented. +Erroneous code example: + +```compile_fail,E0516 +fn main() { + let x: typeof(92) = 92; +} +``` + +Try using type inference instead. Example: + +``` +fn main() { + let x = 92; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0517.md b/src/librustc_error_codes/error_codes/E0517.md new file mode 100644 index 0000000000..f738d33560 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0517.md @@ -0,0 +1,45 @@ +This error indicates that a `#[repr(..)]` attribute was placed on an +unsupported item. + +Examples of erroneous code: + +```compile_fail,E0517 +#[repr(C)] +type Foo = u8; + +#[repr(packed)] +enum Foo {Bar, Baz} + +#[repr(u8)] +struct Foo {bar: bool, baz: bool} + +#[repr(C)] +impl Foo { + // ... +} +``` + +* The `#[repr(C)]` attribute can only be placed on structs and enums. +* The `#[repr(packed)]` and `#[repr(simd)]` attributes only work on structs. +* The `#[repr(u8)]`, `#[repr(i16)]`, etc attributes only work on enums. + +These attributes do not work on typedefs, since typedefs are just aliases. + +Representations like `#[repr(u8)]`, `#[repr(i64)]` are for selecting the +discriminant size for enums with no data fields on any of the variants, e.g. +`enum Color {Red, Blue, Green}`, effectively setting the size of the enum to +the size of the provided type. Such an enum can be cast to a value of the same +type as well. In short, `#[repr(u8)]` makes the enum behave like an integer +with a constrained set of allowed values. + +Only field-less enums can be cast to numerical primitives, so this attribute +will not apply to structs. + +`#[repr(packed)]` reduces padding to make the struct size smaller. The +representation of enums isn't strictly defined in Rust, and this attribute +won't work on enums. + +`#[repr(simd)]` will give a struct consisting of a homogeneous series of machine +types (i.e., `u8`, `i32`, etc) a representation that permits vectorization via +SIMD. This doesn't make much sense for enums since they don't consist of a +single list of data. diff --git a/src/librustc_error_codes/error_codes/E0518.md b/src/librustc_error_codes/error_codes/E0518.md new file mode 100644 index 0000000000..1af9a3735f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0518.md @@ -0,0 +1,23 @@ +This error indicates that an `#[inline(..)]` attribute was incorrectly placed +on something other than a function or method. + +Examples of erroneous code: + +```compile_fail,E0518 +#[inline(always)] +struct Foo; + +#[inline(never)] +impl Foo { + // ... +} +``` + +`#[inline]` hints the compiler whether or not to attempt to inline a method or +function. By default, the compiler does a pretty good job of figuring this out +itself, but if you feel the need for annotations, `#[inline(always)]` and +`#[inline(never)]` can override or force the compiler's decision. + +If you wish to apply this attribute to all methods in an impl, manually annotate +each method; it is not possible to annotate the entire impl with an `#[inline]` +attribute. diff --git a/src/librustc_error_codes/error_codes/E0520.md b/src/librustc_error_codes/error_codes/E0520.md new file mode 100644 index 0000000000..e8a2b4da08 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0520.md @@ -0,0 +1,59 @@ +A non-default implementation was already made on this type so it cannot be +specialized further. Erroneous code example: + +```compile_fail,E0520 +#![feature(specialization)] + +trait SpaceLlama { + fn fly(&self); +} + +// applies to all T +impl SpaceLlama for T { + default fn fly(&self) {} +} + +// non-default impl +// applies to all `Clone` T and overrides the previous impl +impl SpaceLlama for T { + fn fly(&self) {} +} + +// since `i32` is clone, this conflicts with the previous implementation +impl SpaceLlama for i32 { + default fn fly(&self) {} + // error: item `fly` is provided by an `impl` that specializes + // another, but the item in the parent `impl` is not marked + // `default` and so it cannot be specialized. +} +``` + +Specialization only allows you to override `default` functions in +implementations. + +To fix this error, you need to mark all the parent implementations as default. +Example: + +``` +#![feature(specialization)] + +trait SpaceLlama { + fn fly(&self); +} + +// applies to all T +impl SpaceLlama for T { + default fn fly(&self) {} // This is a parent implementation. +} + +// applies to all `Clone` T; overrides the previous impl +impl SpaceLlama for T { + default fn fly(&self) {} // This is a parent implementation but was + // previously not a default one, causing the error +} + +// applies to i32, overrides the previous two impls +impl SpaceLlama for i32 { + fn fly(&self) {} // And now that's ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0522.md b/src/librustc_error_codes/error_codes/E0522.md new file mode 100644 index 0000000000..e4756c384c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0522.md @@ -0,0 +1,14 @@ +The lang attribute is intended for marking special items that are built-in to +Rust itself. This includes special traits (like `Copy` and `Sized`) that affect +how the compiler behaves, as well as special functions that may be automatically +invoked (such as the handler for out-of-bounds accesses when indexing a slice). +Erroneous code example: + +```compile_fail,E0522 +#![feature(lang_items)] + +#[lang = "cookie"] +fn cookie() -> ! { // error: definition of an unknown language item: `cookie` + loop {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0524.md b/src/librustc_error_codes/error_codes/E0524.md new file mode 100644 index 0000000000..bab241b5a9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0524.md @@ -0,0 +1,60 @@ +A variable which requires unique access is being used in more than one closure +at the same time. + +Erroneous code example: + +```compile_fail,E0524 +fn set(x: &mut isize) { + *x += 4; +} + +fn dragoooon(x: &mut isize) { + let mut c1 = || set(x); + let mut c2 = || set(x); // error! + + c2(); + c1(); +} +``` + +To solve this issue, multiple solutions are available. First, is it required +for this variable to be used in more than one closure at a time? If it is the +case, use reference counted types such as `Rc` (or `Arc` if it runs +concurrently): + +``` +use std::rc::Rc; +use std::cell::RefCell; + +fn set(x: &mut isize) { + *x += 4; +} + +fn dragoooon(x: &mut isize) { + let x = Rc::new(RefCell::new(x)); + let y = Rc::clone(&x); + let mut c1 = || { let mut x2 = x.borrow_mut(); set(&mut x2); }; + let mut c2 = || { let mut x2 = y.borrow_mut(); set(&mut x2); }; // ok! + + c2(); + c1(); +} +``` + +If not, just run closures one at a time: + +``` +fn set(x: &mut isize) { + *x += 4; +} + +fn dragoooon(x: &mut isize) { + { // This block isn't necessary since non-lexical lifetimes, it's just to + // make it more clear. + let mut c1 = || set(&mut *x); + c1(); + } // `c1` has been dropped here so we're free to use `x` again! + let mut c2 = || set(&mut *x); + c2(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0525.md b/src/librustc_error_codes/error_codes/E0525.md new file mode 100644 index 0000000000..95e5f362bd --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0525.md @@ -0,0 +1,40 @@ +A closure was used but didn't implement the expected trait. + +Erroneous code example: + +```compile_fail,E0525 +struct X; + +fn foo(_: T) {} +fn bar(_: T) {} + +fn main() { + let x = X; + let closure = |_| foo(x); // error: expected a closure that implements + // the `Fn` trait, but this closure only + // implements `FnOnce` + bar(closure); +} +``` + +In the example above, `closure` is an `FnOnce` closure whereas the `bar` +function expected an `Fn` closure. In this case, it's simple to fix the issue, +you just have to implement `Copy` and `Clone` traits on `struct X` and it'll +be ok: + +``` +#[derive(Clone, Copy)] // We implement `Clone` and `Copy` traits. +struct X; + +fn foo(_: T) {} +fn bar(_: T) {} + +fn main() { + let x = X; + let closure = |_| foo(x); + bar(closure); // ok! +} +``` + +To understand better how closures work in Rust, read: +https://doc.rust-lang.org/book/ch13-01-closures.html diff --git a/src/librustc_error_codes/error_codes/E0527.md b/src/librustc_error_codes/error_codes/E0527.md new file mode 100644 index 0000000000..4bff39dc77 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0527.md @@ -0,0 +1,28 @@ +The number of elements in an array or slice pattern differed from the number of +elements in the array being matched. + +Example of erroneous code: + +```compile_fail,E0527 +let r = &[1, 2, 3, 4]; +match r { + &[a, b] => { // error: pattern requires 2 elements but array + // has 4 + println!("a={}, b={}", a, b); + } +} +``` + +Ensure that the pattern is consistent with the size of the matched +array. Additional elements can be matched with `..`: + +``` +#![feature(slice_patterns)] + +let r = &[1, 2, 3, 4]; +match r { + &[a, b, ..] => { // ok! + println!("a={}, b={}", a, b); + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0528.md b/src/librustc_error_codes/error_codes/E0528.md new file mode 100644 index 0000000000..4b6ea24699 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0528.md @@ -0,0 +1,31 @@ +An array or slice pattern required more elements than were present in the +matched array. + +Example of erroneous code: + +```compile_fail,E0528 +#![feature(slice_patterns)] + +let r = &[1, 2]; +match r { + &[a, b, c, rest @ ..] => { // error: pattern requires at least 3 + // elements but array has 2 + println!("a={}, b={}, c={} rest={:?}", a, b, c, rest); + } +} +``` + +Ensure that the matched array has at least as many elements as the pattern +requires. You can match an arbitrary number of remaining elements with `..`: + +``` +#![feature(slice_patterns)] + +let r = &[1, 2, 3, 4, 5]; +match r { + &[a, b, c, rest @ ..] => { // ok! + // prints `a=1, b=2, c=3 rest=[4, 5]` + println!("a={}, b={}, c={} rest={:?}", a, b, c, rest); + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0529.md b/src/librustc_error_codes/error_codes/E0529.md new file mode 100644 index 0000000000..013f438ba9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0529.md @@ -0,0 +1,24 @@ +An array or slice pattern was matched against some other type. + +Example of erroneous code: + +```compile_fail,E0529 +let r: f32 = 1.0; +match r { + [a, b] => { // error: expected an array or slice, found `f32` + println!("a={}, b={}", a, b); + } +} +``` + +Ensure that the pattern and the expression being matched on are of consistent +types: + +``` +let r = [1.0, 2.0]; +match r { + [a, b] => { // ok! + println!("a={}, b={}", a, b); + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0530.md b/src/librustc_error_codes/error_codes/E0530.md new file mode 100644 index 0000000000..502f674fc1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0530.md @@ -0,0 +1,32 @@ +A binding shadowed something it shouldn't. + +Erroneous code example: + +```compile_fail,E0530 +static TEST: i32 = 0; + +let r: (i32, i32) = (0, 0); +match r { + TEST => {} // error: match bindings cannot shadow statics +} +``` + +To fix this error, just change the binding's name in order to avoid shadowing +one of the following: + +* struct name +* struct/enum variant +* static +* const +* associated const + +Fixed example: + +``` +static TEST: i32 = 0; + +let r: (i32, i32) = (0, 0); +match r { + something => {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0531.md b/src/librustc_error_codes/error_codes/E0531.md new file mode 100644 index 0000000000..2814046fbd --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0531.md @@ -0,0 +1,42 @@ +An unknown tuple struct/variant has been used. + +Erroneous code example: + +```compile_fail,E0531 +let Type(x) = Type(12); // error! +match Bar(12) { + Bar(x) => {} // error! + _ => {} +} +``` + +In most cases, it's either a forgotten import or a typo. However, let's look at +how you can have such a type: + +```edition2018 +struct Type(u32); // this is a tuple struct + +enum Foo { + Bar(u32), // this is a tuple variant +} + +use Foo::*; // To use Foo's variant directly, we need to import them in + // the scope. +``` + +Either way, it should work fine with our previous code: + +```edition2018 +struct Type(u32); + +enum Foo { + Bar(u32), +} +use Foo::*; + +let Type(x) = Type(12); // ok! +match Type(12) { + Type(x) => {} // ok! + _ => {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0532.md b/src/librustc_error_codes/error_codes/E0532.md new file mode 100644 index 0000000000..6fb315a371 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0532.md @@ -0,0 +1,38 @@ +Pattern arm did not match expected kind. + +Erroneous code example: + +```compile_fail,E0532 +enum State { + Succeeded, + Failed(String), +} + +fn print_on_failure(state: &State) { + match *state { + // error: expected unit struct, unit variant or constant, found tuple + // variant `State::Failed` + State::Failed => println!("Failed"), + _ => () + } +} +``` + +To fix this error, ensure the match arm kind is the same as the expression +matched. + +Fixed example: + +``` +enum State { + Succeeded, + Failed(String), +} + +fn print_on_failure(state: &State) { + match *state { + State::Failed(ref msg) => println!("Failed with {}", msg), + _ => () + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0533.md b/src/librustc_error_codes/error_codes/E0533.md new file mode 100644 index 0000000000..279d728caa --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0533.md @@ -0,0 +1,34 @@ +An item which isn't a unit struct, a variant, nor a constant has been used as a +match pattern. + +Erroneous code example: + +```compile_fail,E0533 +struct Tortoise; + +impl Tortoise { + fn turtle(&self) -> u32 { 0 } +} + +match 0u32 { + Tortoise::turtle => {} // Error! + _ => {} +} +if let Tortoise::turtle = 0u32 {} // Same error! +``` + +If you want to match against a value returned by a method, you need to bind the +value first: + +``` +struct Tortoise; + +impl Tortoise { + fn turtle(&self) -> u32 { 0 } +} + +match 0u32 { + x if x == Tortoise.turtle() => {} // Bound into `x` then we compare it! + _ => {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0534.md b/src/librustc_error_codes/error_codes/E0534.md new file mode 100644 index 0000000000..e50b84764b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0534.md @@ -0,0 +1,35 @@ +The `inline` attribute was malformed. + +Erroneous code example: + +```ignore (compile_fail not working here; see Issue #43707) +#[inline()] // error: expected one argument +pub fn something() {} + +fn main() {} +``` + +The parenthesized `inline` attribute requires the parameter to be specified: + +``` +#[inline(always)] +fn something() {} +``` + +or: + +``` +#[inline(never)] +fn something() {} +``` + +Alternatively, a paren-less version of the attribute may be used to hint the +compiler about inlining opportunity: + +``` +#[inline] +fn something() {} +``` + +For more information about the inline attribute, read: +https://doc.rust-lang.org/reference.html#inline-attributes diff --git a/src/librustc_error_codes/error_codes/E0535.md b/src/librustc_error_codes/error_codes/E0535.md new file mode 100644 index 0000000000..e9abfe5dda --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0535.md @@ -0,0 +1,28 @@ +An unknown argument was given to the `inline` attribute. + +Erroneous code example: + +```ignore (compile_fail not working here; see Issue #43707) +#[inline(unknown)] // error: invalid argument +pub fn something() {} + +fn main() {} +``` + +The `inline` attribute only supports two arguments: + + * always + * never + +All other arguments given to the `inline` attribute will return this error. +Example: + +``` +#[inline(never)] // ok! +pub fn something() {} + +fn main() {} +``` + +For more information about the inline attribute, https: +read://doc.rust-lang.org/reference.html#inline-attributes diff --git a/src/librustc_error_codes/error_codes/E0536.md b/src/librustc_error_codes/error_codes/E0536.md new file mode 100644 index 0000000000..9006906a70 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0536.md @@ -0,0 +1,22 @@ +The `not` cfg-predicate was malformed. + +Erroneous code example: + +```compile_fail,E0536 +#[cfg(not())] // error: expected 1 cfg-pattern +pub fn something() {} + +pub fn main() {} +``` + +The `not` predicate expects one cfg-pattern. Example: + +``` +#[cfg(not(target_os = "linux"))] // ok! +pub fn something() {} + +pub fn main() {} +``` + +For more information about the cfg attribute, read: +https://doc.rust-lang.org/reference.html#conditional-compilation diff --git a/src/librustc_error_codes/error_codes/E0537.md b/src/librustc_error_codes/error_codes/E0537.md new file mode 100644 index 0000000000..82d8c6188a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0537.md @@ -0,0 +1,28 @@ +An unknown predicate was used inside the `cfg` attribute. + +Erroneous code example: + +```compile_fail,E0537 +#[cfg(unknown())] // error: invalid predicate `unknown` +pub fn something() {} + +pub fn main() {} +``` + +The `cfg` attribute supports only three kinds of predicates: + + * any + * all + * not + +Example: + +``` +#[cfg(not(target_os = "linux"))] // ok! +pub fn something() {} + +pub fn main() {} +``` + +For more information about the cfg attribute, read: +https://doc.rust-lang.org/reference.html#conditional-compilation diff --git a/src/librustc_error_codes/error_codes/E0538.md b/src/librustc_error_codes/error_codes/E0538.md new file mode 100644 index 0000000000..5858771ce8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0538.md @@ -0,0 +1,27 @@ +Attribute contains same meta item more than once. + +Erroneous code example: + +```compile_fail,E0538 +#[deprecated( + since="1.0.0", + note="First deprecation note.", + note="Second deprecation note." // error: multiple same meta item +)] +fn deprecated_function() {} +``` + +Meta items are the key-value pairs inside of an attribute. Each key may only be +used once in each attribute. + +To fix the problem, remove all but one of the meta items with the same key. + +Example: + +``` +#[deprecated( + since="1.0.0", + note="First deprecation note." +)] +fn deprecated_function() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0541.md b/src/librustc_error_codes/error_codes/E0541.md new file mode 100644 index 0000000000..96334088fe --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0541.md @@ -0,0 +1,29 @@ +An unknown meta item was used. + +Erroneous code example: + +```compile_fail,E0541 +#[deprecated( + since="1.0.0", + // error: unknown meta item + reason="Example invalid meta item. Should be 'note'") +] +fn deprecated_function() {} +``` + +Meta items are the key-value pairs inside of an attribute. The keys provided +must be one of the valid keys for the specified attribute. + +To fix the problem, either remove the unknown meta item, or rename it if you +provided the wrong name. + +In the erroneous code example above, the wrong name was provided, so changing +to a correct one it will fix the error. Example: + +``` +#[deprecated( + since="1.0.0", + note="This is a valid meta item for the deprecated attribute." +)] +fn deprecated_function() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0550.md b/src/librustc_error_codes/error_codes/E0550.md new file mode 100644 index 0000000000..1487d70184 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0550.md @@ -0,0 +1,16 @@ +More than one `deprecated` attribute has been put on an item. + +Erroneous code example: + +```compile_fail,E0550 +#[deprecated(note = "because why not?")] +#[deprecated(note = "right?")] // error! +fn the_banished() {} +``` + +The `deprecated` attribute can only be present **once** on an item. + +``` +#[deprecated(note = "because why not, right?")] +fn the_banished() {} // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0551.md b/src/librustc_error_codes/error_codes/E0551.md new file mode 100644 index 0000000000..53db559a4f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0551.md @@ -0,0 +1,16 @@ +An invalid meta-item was used inside an attribute. + +Erroneous code example: + +```compile_fail,E0551 +#[deprecated(note)] // error! +fn i_am_deprecated() {} +``` + +Meta items are the key-value pairs inside of an attribute. To fix this issue, +you need to give a value to the `note` key. Example: + +``` +#[deprecated(note = "because")] // ok! +fn i_am_deprecated() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0552.md b/src/librustc_error_codes/error_codes/E0552.md new file mode 100644 index 0000000000..0fbc861fb7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0552.md @@ -0,0 +1,27 @@ +A unrecognized representation attribute was used. + +Erroneous code example: + +```compile_fail,E0552 +#[repr(D)] // error: unrecognized representation hint +struct MyStruct { + my_field: usize +} +``` + +You can use a `repr` attribute to tell the compiler how you want a struct or +enum to be laid out in memory. + +Make sure you're using one of the supported options: + +``` +#[repr(C)] // ok! +struct MyStruct { + my_field: usize +} +``` + +For more information about specifying representations, see the ["Alternative +Representations" section] of the Rustonomicon. + +["Alternative Representations" section]: https://doc.rust-lang.org/nomicon/other-reprs.html diff --git a/src/librustc_error_codes/error_codes/E0554.md b/src/librustc_error_codes/error_codes/E0554.md new file mode 100644 index 0000000000..e25212983e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0554.md @@ -0,0 +1,12 @@ +Feature attributes are only allowed on the nightly release channel. Stable or +beta compilers will not comply. + +Example of erroneous code (on a stable compiler): + +```ignore (depends on release channel) +#![feature(non_ascii_idents)] // error: `#![feature]` may not be used on the + // stable release channel +``` + +If you need the feature, make sure to use a nightly release of the compiler +(but be warned that the feature may be removed or altered in the future). diff --git a/src/librustc_error_codes/error_codes/E0556.md b/src/librustc_error_codes/error_codes/E0556.md new file mode 100644 index 0000000000..2aac8240d2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0556.md @@ -0,0 +1,16 @@ +The `feature` attribute was badly formed. + +Erroneous code example: + +```compile_fail,E0556 +#![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] // error! +#![feature] // error! +#![feature = "foo"] // error! +``` + +The `feature` attribute only accept a "feature flag" and can only be used on +nightly. Example: + +```ignore (only works in nightly) +#![feature(flag)] +``` diff --git a/src/librustc_error_codes/error_codes/E0557.md b/src/librustc_error_codes/error_codes/E0557.md new file mode 100644 index 0000000000..f330efe593 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0557.md @@ -0,0 +1,9 @@ +A feature attribute named a feature that has been removed. + +Erroneous code example: + +```compile_fail,E0557 +#![feature(managed_boxes)] // error: feature has been removed +``` + +Delete the offending feature attribute. diff --git a/src/librustc_error_codes/error_codes/E0559.md b/src/librustc_error_codes/error_codes/E0559.md new file mode 100644 index 0000000000..b9f7b65089 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0559.md @@ -0,0 +1,22 @@ +An unknown field was specified into an enum's structure variant. + +Erroneous code example: + +```compile_fail,E0559 +enum Field { + Fool { x: u32 }, +} + +let s = Field::Fool { joke: 0 }; +// error: struct variant `Field::Fool` has no field named `joke` +``` + +Verify you didn't misspell the field's name or that the field exists. Example: + +``` +enum Field { + Fool { joke: u32 }, +} + +let s = Field::Fool { joke: 0 }; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0560.md b/src/librustc_error_codes/error_codes/E0560.md new file mode 100644 index 0000000000..7185bf38c2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0560.md @@ -0,0 +1,23 @@ +An unknown field was specified into a structure. + +Erroneous code example: + +```compile_fail,E0560 +struct Simba { + mother: u32, +} + +let s = Simba { mother: 1, father: 0 }; +// error: structure `Simba` has no field named `father` +``` + +Verify you didn't misspell the field's name or that the field exists. Example: + +``` +struct Simba { + mother: u32, + father: u32, +} + +let s = Simba { mother: 1, father: 0 }; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0561.md b/src/librustc_error_codes/error_codes/E0561.md new file mode 100644 index 0000000000..5290018901 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0561.md @@ -0,0 +1,25 @@ +A non-ident or non-wildcard pattern has been used as a parameter of a function +pointer type. + +Erroneous code example: + +```compile_fail,E0561 +type A1 = fn(mut param: u8); // error! +type A2 = fn(¶m: u32); // error! +``` + +When using an alias over a function type, you cannot e.g. denote a parameter as +being mutable. + +To fix the issue, remove patterns (`_` is allowed though). Example: + +``` +type A1 = fn(param: u8); // ok! +type A2 = fn(_: u32); // ok! +``` + +You can also omit the parameter name: + +``` +type A3 = fn(i16); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0562.md b/src/librustc_error_codes/error_codes/E0562.md new file mode 100644 index 0000000000..95f038df56 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0562.md @@ -0,0 +1,33 @@ +Abstract return types (written `impl Trait` for some trait `Trait`) are only +allowed as function and inherent impl return types. + +Erroneous code example: + +```compile_fail,E0562 +fn main() { + let count_to_ten: impl Iterator = 0..10; + // error: `impl Trait` not allowed outside of function and inherent method + // return types + for i in count_to_ten { + println!("{}", i); + } +} +``` + +Make sure `impl Trait` only appears in return-type position. + +``` +fn count_to_n(n: usize) -> impl Iterator { + 0..n +} + +fn main() { + for i in count_to_n(10) { // ok! + println!("{}", i); + } +} +``` + +See [RFC 1522] for more details. + +[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md diff --git a/src/librustc_error_codes/error_codes/E0565.md b/src/librustc_error_codes/error_codes/E0565.md new file mode 100644 index 0000000000..1faedf4593 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0565.md @@ -0,0 +1,17 @@ +A literal was used in a built-in attribute that doesn't support literals. + +Erroneous code example: + +```ignore (compile_fail not working here; see Issue #43707) +#[inline("always")] // error: unsupported literal +pub fn something() {} +``` + +Literals in attributes are new and largely unsupported in built-in attributes. +Work to support literals where appropriate is ongoing. Try using an unquoted +name instead: + +``` +#[inline(always)] +pub fn something() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0566.md b/src/librustc_error_codes/error_codes/E0566.md new file mode 100644 index 0000000000..62fb66f614 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0566.md @@ -0,0 +1,18 @@ +Conflicting representation hints have been used on a same item. + +Erroneous code example: + +``` +#[repr(u32, u64)] // warning! +enum Repr { A } +``` + +In most cases (if not all), using just one representation hint is more than +enough. If you want to have a representation hint depending on the current +architecture, use `cfg_attr`. Example: + +``` +#[cfg_attr(linux, repr(u32))] +#[cfg_attr(not(linux), repr(u64))] +enum Repr { A } +``` diff --git a/src/librustc_error_codes/error_codes/E0567.md b/src/librustc_error_codes/error_codes/E0567.md new file mode 100644 index 0000000000..ec1ed03c12 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0567.md @@ -0,0 +1,25 @@ +Generics have been used on an auto trait. + +Erroneous code example: + +```compile_fail,E0567 +#![feature(optin_builtin_traits)] + +auto trait Generic {} // error! + +fn main() {} +``` + +Since an auto trait is implemented on all existing types, the +compiler would not be able to infer the types of the trait's generic +parameters. + +To fix this issue, just remove the generics: + +``` +#![feature(optin_builtin_traits)] + +auto trait Generic {} // ok! + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0568.md b/src/librustc_error_codes/error_codes/E0568.md new file mode 100644 index 0000000000..a37381f1cb --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0568.md @@ -0,0 +1,26 @@ +A super trait has been added to an auto trait. + +Erroneous code example: + +```compile_fail,E0568 +#![feature(optin_builtin_traits)] + +auto trait Bound : Copy {} // error! + +fn main() {} +``` + +Since an auto trait is implemented on all existing types, adding a super trait +would filter out a lot of those types. In the current example, almost none of +all the existing types could implement `Bound` because very few of them have the +`Copy` trait. + +To fix this issue, just remove the super trait: + +``` +#![feature(optin_builtin_traits)] + +auto trait Bound {} // ok! + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0569.md b/src/librustc_error_codes/error_codes/E0569.md new file mode 100644 index 0000000000..4cba0cf9c9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0569.md @@ -0,0 +1,18 @@ +If an impl has a generic parameter with the `#[may_dangle]` attribute, then +that impl must be declared as an `unsafe impl. + +Erroneous code example: + +```compile_fail,E0569 +#![feature(dropck_eyepatch)] + +struct Foo(X); +impl<#[may_dangle] X> Drop for Foo { + fn drop(&mut self) { } +} +``` + +In this example, we are asserting that the destructor for `Foo` will not +access any data of type `X`, and require this assertion to be true for +overall safety in our program. The compiler does not currently attempt to +verify this assertion; therefore we must tag this `impl` as unsafe. diff --git a/src/librustc_error_codes/error_codes/E0570.md b/src/librustc_error_codes/error_codes/E0570.md new file mode 100644 index 0000000000..bf9615f873 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0570.md @@ -0,0 +1,7 @@ +The requested ABI is unsupported by the current target. + +The rust compiler maintains for each target a blacklist of ABIs unsupported on +that target. If an ABI is present in such a list this usually means that the +target / ABI combination is currently unsupported by llvm. + +If necessary, you can circumvent this check using custom target specifications. diff --git a/src/librustc_error_codes/error_codes/E0571.md b/src/librustc_error_codes/error_codes/E0571.md new file mode 100644 index 0000000000..c2a3a8d758 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0571.md @@ -0,0 +1,31 @@ +A `break` statement with an argument appeared in a non-`loop` loop. + +Example of erroneous code: + +```compile_fail,E0571 +# let mut i = 1; +# fn satisfied(n: usize) -> bool { n % 23 == 0 } +let result = while true { + if satisfied(i) { + break 2*i; // error: `break` with value from a `while` loop + } + i += 1; +}; +``` + +The `break` statement can take an argument (which will be the value of the loop +expression if the `break` statement is executed) in `loop` loops, but not +`for`, `while`, or `while let` loops. + +Make sure `break value;` statements only occur in `loop` loops: + +``` +# let mut i = 1; +# fn satisfied(n: usize) -> bool { n % 23 == 0 } +let result = loop { // ok! + if satisfied(i) { + break 2*i; + } + i += 1; +}; +``` diff --git a/src/librustc_error_codes/error_codes/E0572.md b/src/librustc_error_codes/error_codes/E0572.md new file mode 100644 index 0000000000..b2660650f1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0572.md @@ -0,0 +1,24 @@ +A return statement was found outside of a function body. + +Erroneous code example: + +```compile_fail,E0572 +const FOO: u32 = return 0; // error: return statement outside of function body + +fn main() {} +``` + +To fix this issue, just remove the return keyword or move the expression into a +function. Example: + +``` +const FOO: u32 = 0; + +fn some_fn() -> u32 { + return FOO; +} + +fn main() { + some_fn(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0573.md b/src/librustc_error_codes/error_codes/E0573.md new file mode 100644 index 0000000000..6021ed0ef2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0573.md @@ -0,0 +1,71 @@ +Something other than a type has been used when one was expected. + +Erroneous code examples: + +```compile_fail,E0573 +enum Dragon { + Born, +} + +fn oblivion() -> Dragon::Born { // error! + Dragon::Born +} + +const HOBBIT: u32 = 2; +impl HOBBIT {} // error! + +enum Wizard { + Gandalf, + Saruman, +} + +trait Isengard { + fn wizard(_: Wizard::Saruman); // error! +} +``` + +In all these errors, a type was expected. For example, in the first error, if +we want to return the `Born` variant from the `Dragon` enum, we must set the +function to return the enum and not its variant: + +``` +enum Dragon { + Born, +} + +fn oblivion() -> Dragon { // ok! + Dragon::Born +} +``` + +In the second error, you can't implement something on an item, only on types. +We would need to create a new type if we wanted to do something similar: + +``` +struct Hobbit(u32); // we create a new type + +const HOBBIT: Hobbit = Hobbit(2); +impl Hobbit {} // ok! +``` + +In the third case, we tried to only expect one variant of the `Wizard` enum, +which is not possible. To make this work, we need to using pattern matching +over the `Wizard` enum: + +``` +enum Wizard { + Gandalf, + Saruman, +} + +trait Isengard { + fn wizard(w: Wizard) { // ok! + match w { + Wizard::Saruman => { + // do something + } + _ => {} // ignore everything else + } + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0574.md b/src/librustc_error_codes/error_codes/E0574.md new file mode 100644 index 0000000000..8154d5b782 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0574.md @@ -0,0 +1,47 @@ +Something other than a struct, variant or union has been used when one was +expected. + +Erroneous code example: + +```compile_fail,E0574 +mod Mordor {} + +let sauron = Mordor { x: () }; // error! + +enum Jak { + Daxter { i: isize }, +} + +let eco = Jak::Daxter { i: 1 }; +match eco { + Jak { i } => {} // error! +} +``` + +In all these errors, a type was expected. For example, in the first error, +we tried to instantiate the `Mordor` module, which is impossible. If you want +to instantiate a type inside a module, you can do it as follow: + +``` +mod Mordor { + pub struct TheRing { + pub x: usize, + } +} + +let sauron = Mordor::TheRing { x: 1 }; // ok! +``` + +In the second error, we tried to bind the `Jak` enum directly, which is not +possible: you can only bind one of its variants. To do so: + +``` +enum Jak { + Daxter { i: isize }, +} + +let eco = Jak::Daxter { i: 1 }; +match eco { + Jak::Daxter { i } => {} // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0575.md b/src/librustc_error_codes/error_codes/E0575.md new file mode 100644 index 0000000000..903939a9af --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0575.md @@ -0,0 +1,50 @@ +Something other than a type or an associated type was given. + +Erroneous code example: + +```compile_fail,E0575 +enum Rick { Morty } + +let _: ::Morty; // error! + +trait Age { + type Empire; + fn Mythology() {} +} + +impl Age for u8 { + type Empire = u16; +} + +let _: ::Mythology; // error! +``` + +In both cases, we're declaring a variable (called `_`) and we're giving it a +type. However, `::Morty` and `::Mythology` aren't types, +therefore the compiler throws an error. + +`::Morty` is an enum variant, you cannot use a variant as a type, +you have to use the enum directly: + +``` +enum Rick { Morty } + +let _: Rick; // ok! +``` + +`::Mythology` is a trait method, which is definitely not a type. +However, the `Age` trait provides an associated type `Empire` which can be +used as a type: + +``` +trait Age { + type Empire; + fn Mythology() {} +} + +impl Age for u8 { + type Empire = u16; +} + +let _: ::Empire; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0576.md b/src/librustc_error_codes/error_codes/E0576.md new file mode 100644 index 0000000000..8eead4e7e3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0576.md @@ -0,0 +1,22 @@ +An associated item wasn't found in the given type. + +Erroneous code example: + +```compile_fail,E0576 +trait Hello { + type Who; + + fn hello() -> ::You; // error! +} +``` + +In this example, we tried to use the non-existent associated type `You` of the +`Hello` trait. To fix this error, use an existing associated type: + +``` +trait Hello { + type Who; + + fn hello() -> ::Who; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0577.md b/src/librustc_error_codes/error_codes/E0577.md new file mode 100644 index 0000000000..1feb9c0acf --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0577.md @@ -0,0 +1,24 @@ +Something other than a module was found in visibility scope. + +Erroneous code example: + +```compile_fail,E0577,edition2018 +pub struct Sea; + +pub (in crate::Sea) struct Shark; // error! + +fn main() {} +``` + +`Sea` is not a module, therefore it is invalid to use it in a visibility path. +To fix this error we need to ensure `Sea` is a module. + +Please note that the visibility scope can only be applied on ancestors! + +```edition2018 +pub mod Sea { + pub (in crate::Sea) struct Shark; // ok! +} + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0578.md b/src/librustc_error_codes/error_codes/E0578.md new file mode 100644 index 0000000000..fca8975728 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0578.md @@ -0,0 +1,25 @@ +A module cannot be found and therefore, the visibility cannot be determined. + +Erroneous code example: + +```compile_fail,E0578,edition2018 +foo!(); + +pub (in ::Sea) struct Shark; // error! + +fn main() {} +``` + +Because of the call to the `foo` macro, the compiler guesses that the missing +module could be inside it and fails because the macro definition cannot be +found. + +To fix this error, please be sure that the module is in scope: + +```edition2018 +pub mod Sea { + pub (in crate::Sea) struct Shark; +} + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0579.md b/src/librustc_error_codes/error_codes/E0579.md new file mode 100644 index 0000000000..225e27f0ca --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0579.md @@ -0,0 +1,19 @@ +When matching against an exclusive range, the compiler verifies that the range +is non-empty. Exclusive range patterns include the start point but not the end +point, so this is equivalent to requiring the start of the range to be less +than the end of the range. + +Erroneous code example: + +```compile_fail,E0579 +#![feature(exclusive_range_pattern)] + +fn main() { + match 5u32 { + // This range is ok, albeit pointless. + 1 .. 2 => {} + // This range is empty, and the compiler can tell. + 5 .. 5 => {} // error! + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0580.md b/src/librustc_error_codes/error_codes/E0580.md new file mode 100644 index 0000000000..260575d5de --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0580.md @@ -0,0 +1,21 @@ +The `main` function was incorrectly declared. + +Erroneous code example: + +```compile_fail,E0580 +fn main(x: i32) { // error: main function has wrong type + println!("{}", x); +} +``` + +The `main` function prototype should never take arguments. +Example: + +``` +fn main() { + // your code +} +``` + +If you want to get command-line arguments, use `std::env::args`. To exit with a +specified exit code, use `std::process::exit`. diff --git a/src/librustc_error_codes/error_codes/E0581.md b/src/librustc_error_codes/error_codes/E0581.md new file mode 100644 index 0000000000..947ec255a9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0581.md @@ -0,0 +1,28 @@ +In a `fn` type, a lifetime appears only in the return type, +and not in the arguments types. + +Erroneous code example: + +```compile_fail,E0581 +fn main() { + // Here, `'a` appears only in the return type: + let x: for<'a> fn() -> &'a i32; +} +``` + +To fix this issue, either use the lifetime in the arguments, or use +`'static`. Example: + +``` +fn main() { + // Here, `'a` appears only in the return type: + let x: for<'a> fn(&'a i32) -> &'a i32; + let y: fn() -> &'static i32; +} +``` + +Note: The examples above used to be (erroneously) accepted by the +compiler, but this was since corrected. See [issue #33685] for more +details. + +[issue #33685]: https://github.com/rust-lang/rust/issues/33685 diff --git a/src/librustc_error_codes/error_codes/E0582.md b/src/librustc_error_codes/error_codes/E0582.md new file mode 100644 index 0000000000..c0cf44852c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0582.md @@ -0,0 +1,34 @@ +A lifetime appears only in an associated-type binding, +and not in the input types to the trait. + +Erroneous code example: + +```compile_fail,E0582 +fn bar(t: F) + // No type can satisfy this requirement, since `'a` does not + // appear in any of the input types (here, `i32`): + where F: for<'a> Fn(i32) -> Option<&'a i32> +{ +} + +fn main() { } +``` + +To fix this issue, either use the lifetime in the inputs, or use +`'static`. Example: + +``` +fn bar(t: F, u: G) + where F: for<'a> Fn(&'a i32) -> Option<&'a i32>, + G: Fn(i32) -> Option<&'static i32>, +{ +} + +fn main() { } +``` + +Note: The examples above used to be (erroneously) accepted by the +compiler, but this was since corrected. See [issue #33685] for more +details. + +[issue #33685]: https://github.com/rust-lang/rust/issues/33685 diff --git a/src/librustc_error_codes/error_codes/E0583.md b/src/librustc_error_codes/error_codes/E0583.md new file mode 100644 index 0000000000..2dcbbf8855 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0583.md @@ -0,0 +1,14 @@ +A file wasn't found for an out-of-line module. + +Erroneous code example: + +```ignore (compile_fail not working here; see Issue #43707) +mod file_that_doesnt_exist; // error: file not found for module + +fn main() {} +``` + +Please be sure that a file corresponding to the module exists. If you +want to use a module named `file_that_doesnt_exist`, you need to have a file +named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the +same directory. diff --git a/src/librustc_error_codes/error_codes/E0584.md b/src/librustc_error_codes/error_codes/E0584.md new file mode 100644 index 0000000000..8b00655ee7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0584.md @@ -0,0 +1,24 @@ +A doc comment that is not attached to anything has been encountered. + +Erroneous code example: + +```compile_fail,E0584 +trait Island { + fn lost(); + + /// I'm lost! +} +``` + +A little reminder: a doc comment has to be placed before the item it's supposed +to document. So if you want to document the `Island` trait, you need to put a +doc comment before it, not inside it. Same goes for the `lost` method: the doc +comment needs to be before it: + +``` +/// I'm THE island! +trait Island { + /// I'm lost! + fn lost(); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0585.md b/src/librustc_error_codes/error_codes/E0585.md new file mode 100644 index 0000000000..de27cc19d1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0585.md @@ -0,0 +1,21 @@ +A documentation comment that doesn't document anything was found. + +Erroneous code example: + +```compile_fail,E0585 +fn main() { + // The following doc comment will fail: + /// This is a useless doc comment! +} +``` + +Documentation comments need to be followed by items, including functions, +types, modules, etc. Examples: + +``` +/// I'm documenting the following struct: +struct Foo; + +/// I'm documenting the following function: +fn foo() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0586.md b/src/librustc_error_codes/error_codes/E0586.md new file mode 100644 index 0000000000..bc6572ecad --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0586.md @@ -0,0 +1,29 @@ +An inclusive range was used with no end. + +Erroneous code example: + +```compile_fail,E0586 +fn main() { + let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; + let x = &tmp[1..=]; // error: inclusive range was used with no end +} +``` + +An inclusive range needs an end in order to *include* it. If you just need a +start and no end, use a non-inclusive range (with `..`): + +``` +fn main() { + let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; + let x = &tmp[1..]; // ok! +} +``` + +Or put an end to your inclusive range: + +``` +fn main() { + let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; + let x = &tmp[1..=3]; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0587.md b/src/librustc_error_codes/error_codes/E0587.md new file mode 100644 index 0000000000..ee9031dc37 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0587.md @@ -0,0 +1,16 @@ +A type has both `packed` and `align` representation hints. + +Erroneous code example: + +```compile_fail,E0587 +#[repr(packed, align(8))] // error! +struct Umbrella(i32); +``` + +You cannot use `packed` and `align` hints on a same type. If you want to pack a +type to a given size, you should provide a size to packed: + +``` +#[repr(packed)] // ok! +struct Umbrella(i32); +``` diff --git a/src/librustc_error_codes/error_codes/E0588.md b/src/librustc_error_codes/error_codes/E0588.md new file mode 100644 index 0000000000..040c7a02ef --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0588.md @@ -0,0 +1,24 @@ +A type with `packed` representation hint has a field with `align` +representation hint. + +Erroneous code example: + +```compile_fail,E0588 +#[repr(align(16))] +struct Aligned(i32); + +#[repr(packed)] // error! +struct Packed(Aligned); +``` + +Just like you cannot have both `align` and `packed` representation hints on a +same type, a `packed` type cannot contain another type with the `align` +representation hint. However, you can do the opposite: + +``` +#[repr(packed)] +struct Packed(i32); + +#[repr(align(16))] // ok! +struct Aligned(Packed); +``` diff --git a/src/librustc_error_codes/error_codes/E0589.md b/src/librustc_error_codes/error_codes/E0589.md new file mode 100644 index 0000000000..5e15a875b0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0589.md @@ -0,0 +1,9 @@ +The value of `N` that was specified for `repr(align(N))` was not a power +of two, or was greater than 2^29. + +```compile_fail,E0589 +#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two +enum Foo { + Bar(u64), +} +``` diff --git a/src/librustc_error_codes/error_codes/E0590.md b/src/librustc_error_codes/error_codes/E0590.md new file mode 100644 index 0000000000..8032e45903 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0590.md @@ -0,0 +1,13 @@ +`break` or `continue` must include a label when used in the condition of a +`while` loop. + +Example of erroneous code: + +```compile_fail +while break {} +``` + +To fix this, add a label specifying which loop is being broken out of: +``` +'foo: while break 'foo {} +``` diff --git a/src/librustc_error_codes/error_codes/E0591.md b/src/librustc_error_codes/error_codes/E0591.md new file mode 100644 index 0000000000..782d4cf29c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0591.md @@ -0,0 +1,75 @@ +Per [RFC 401][rfc401], if you have a function declaration `foo`: + +``` +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: +struct S; +fn foo(x: S) { /* ... */ } +# #[cfg(for_demonstration_only)] +extern "C" { fn foo(x: S); } +# #[cfg(for_demonstration_only)] +impl S { fn foo(self) { /* ... */ } } +``` + +the type of `foo` is **not** `fn(S)`, as one might expect. +Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, +so you rarely notice this: + +``` +# struct S; +# fn foo(_: S) {} +let x: fn(S) = foo; // OK, coerces +``` + +The reason that this matter is that the type `fn(S)` is not specific to +any particular function: it's a function _pointer_. So calling `x()` results +in a virtual call, whereas `foo()` is statically dispatched, because the type +of `foo` tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be +concerned with this distinction. However, you can tell the difference +when using **transmute** to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +```compile_fail,E0591 +extern "C" fn foo(userdata: Box) { + /* ... */ +} + +# fn callback(_: extern "C" fn(*mut i32)) {} +# use std::mem::transmute; +# unsafe { +let f: extern "C" fn(*mut i32) = transmute(foo); +callback(f); +# } +``` + +Here, transmute is being used to convert the types of the fn arguments. +This pattern is incorrect because, because the type of `foo` is a function +**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) +is a function pointer, which is not zero-sized. +This pattern should be rewritten. There are a few possible ways to do this: + +- change the original fn declaration to match the expected signature, + and do the cast in the fn body (the preferred option) +- cast the fn item fo a fn pointer before calling transmute, as shown here: + + ``` + # extern "C" fn foo(_: Box) {} + # use std::mem::transmute; + # unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + # } + ``` + +The same applies to transmutes to `*mut fn()`, which were observed in practice. +Note though that use of this type is generally incorrect. +The intention is typically to describe a function pointer, but just `fn()` +alone suffices for that. `*mut fn()` is a pointer to a fn pointer. +(Since these values are typically just passed to C code, however, this rarely +makes a difference in practice.) + +[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md diff --git a/src/librustc_error_codes/error_codes/E0592.md b/src/librustc_error_codes/error_codes/E0592.md new file mode 100644 index 0000000000..06959b5d76 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0592.md @@ -0,0 +1,31 @@ +This error occurs when you defined methods or associated functions with same +name. + +Erroneous code example: + +```compile_fail,E0592 +struct Foo; + +impl Foo { + fn bar() {} // previous definition here +} + +impl Foo { + fn bar() {} // duplicate definition here +} +``` + +A similar error is E0201. The difference is whether there is one declaration +block or not. To avoid this error, you must give each `fn` a unique name. + +``` +struct Foo; + +impl Foo { + fn bar() {} +} + +impl Foo { + fn baz() {} // define with different name +} +``` diff --git a/src/librustc_error_codes/error_codes/E0593.md b/src/librustc_error_codes/error_codes/E0593.md new file mode 100644 index 0000000000..b32923a9e5 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0593.md @@ -0,0 +1,13 @@ +You tried to supply an `Fn`-based type with an incorrect number of arguments +than what was expected. + +Erroneous code example: + +```compile_fail,E0593 +fn foo(x: F) { } + +fn main() { + // [E0593] closure takes 1 argument but 0 arguments are required + foo(|y| { }); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0594.md b/src/librustc_error_codes/error_codes/E0594.md new file mode 100644 index 0000000000..ad8eb631e6 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0594.md @@ -0,0 +1,23 @@ +A non-mutable value was assigned a value. + +Erroneous code example: + +```compile_fail,E0594 +struct SolarSystem { + earth: i32, +} + +let ss = SolarSystem { earth: 3 }; +ss.earth = 2; // error! +``` + +To fix this error, declare `ss` as mutable by using the `mut` keyword: + +``` +struct SolarSystem { + earth: i32, +} + +let mut ss = SolarSystem { earth: 3 }; // declaring `ss` as mutable +ss.earth = 2; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0595.md b/src/librustc_error_codes/error_codes/E0595.md new file mode 100644 index 0000000000..e672901324 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0595.md @@ -0,0 +1,17 @@ +#### Note: this error code is no longer emitted by the compiler. + +Closures cannot mutate immutable captured variables. + +Erroneous code example: + +```compile_fail,E0594 +let x = 3; // error: closure cannot assign to immutable local variable `x` +let mut c = || { x += 1 }; +``` + +Make the variable binding mutable: + +``` +let mut x = 3; // ok! +let mut c = || { x += 1 }; +``` diff --git a/src/librustc_error_codes/error_codes/E0596.md b/src/librustc_error_codes/error_codes/E0596.md new file mode 100644 index 0000000000..95669309b3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0596.md @@ -0,0 +1,16 @@ +This error occurs because you tried to mutably borrow a non-mutable variable. + +Erroneous code example: + +```compile_fail,E0596 +let x = 1; +let y = &mut x; // error: cannot borrow mutably +``` + +In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it +fails. To fix this error, you need to make `x` mutable: + +``` +let mut x = 1; +let y = &mut x; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0597.md b/src/librustc_error_codes/error_codes/E0597.md new file mode 100644 index 0000000000..3340768fa8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0597.md @@ -0,0 +1,33 @@ +This error occurs because a value was dropped while it was still borrowed + +Erroneous code example: + +```compile_fail,E0597 +struct Foo<'a> { + x: Option<&'a u32>, +} + +let mut x = Foo { x: None }; +{ + let y = 0; + x.x = Some(&y); // error: `y` does not live long enough +} +println!("{:?}", x.x); +``` + +In here, `y` is dropped at the end of the inner scope, but it is borrowed by +`x` until the `println`. To fix the previous example, just remove the scope +so that `y` isn't dropped until after the println + +``` +struct Foo<'a> { + x: Option<&'a u32>, +} + +let mut x = Foo { x: None }; + +let y = 0; +x.x = Some(&y); + +println!("{:?}", x.x); +``` diff --git a/src/librustc_error_codes/error_codes/E0599.md b/src/librustc_error_codes/error_codes/E0599.md new file mode 100644 index 0000000000..c44e60571e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0599.md @@ -0,0 +1,11 @@ +This error occurs when a method is used on a type which doesn't implement it: + +Erroneous code example: + +```compile_fail,E0599 +struct Mouth; + +let x = Mouth; +x.chocolate(); // error: no method named `chocolate` found for type `Mouth` + // in the current scope +``` diff --git a/src/librustc_error_codes/error_codes/E0600.md b/src/librustc_error_codes/error_codes/E0600.md new file mode 100644 index 0000000000..172e2a346c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0600.md @@ -0,0 +1,40 @@ +An unary operator was used on a type which doesn't implement it. + +Example of erroneous code: + +```compile_fail,E0600 +enum Question { + Yes, + No, +} + +!Question::Yes; // error: cannot apply unary operator `!` to type `Question` +``` + +In this case, `Question` would need to implement the `std::ops::Not` trait in +order to be able to use `!` on it. Let's implement it: + +``` +use std::ops::Not; + +enum Question { + Yes, + No, +} + +// We implement the `Not` trait on the enum. +impl Not for Question { + type Output = bool; + + fn not(self) -> bool { + match self { + Question::Yes => false, // If the `Answer` is `Yes`, then it + // returns false. + Question::No => true, // And here we do the opposite. + } + } +} + +assert_eq!(!Question::Yes, false); +assert_eq!(!Question::No, true); +``` diff --git a/src/librustc_error_codes/error_codes/E0601.md b/src/librustc_error_codes/error_codes/E0601.md new file mode 100644 index 0000000000..12ae767c9e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0601.md @@ -0,0 +1,12 @@ +No `main` function was found in a binary crate. To fix this error, add a +`main` function. For example: + +``` +fn main() { + // Your program will start here. + println!("Hello world!"); +} +``` + +If you don't know the basics of Rust, you can go look to the Rust Book to get +started: https://doc.rust-lang.org/book/ diff --git a/src/librustc_error_codes/error_codes/E0602.md b/src/librustc_error_codes/error_codes/E0602.md new file mode 100644 index 0000000000..ca7138a60c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0602.md @@ -0,0 +1,10 @@ +An unknown lint was used on the command line. + +Erroneous example: + +```sh +rustc -D bogus omse_file.rs +``` + +Maybe you just misspelled the lint name or the lint doesn't exist anymore. +Either way, try to update/remove it in order to fix the error. diff --git a/src/librustc_error_codes/error_codes/E0603.md b/src/librustc_error_codes/error_codes/E0603.md new file mode 100644 index 0000000000..69fefce390 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0603.md @@ -0,0 +1,26 @@ +A private item was used outside its scope. + +Erroneous code example: + +```compile_fail,E0603 +mod SomeModule { + const PRIVATE: u32 = 0x_a_bad_1dea_u32; // This const is private, so we + // can't use it outside of the + // `SomeModule` module. +} + +println!("const value: {}", SomeModule::PRIVATE); // error: constant `PRIVATE` + // is private +``` + +In order to fix this error, you need to make the item public by using the `pub` +keyword. Example: + +``` +mod SomeModule { + pub const PRIVATE: u32 = 0x_a_bad_1dea_u32; // We set it public by using the + // `pub` keyword. +} + +println!("const value: {}", SomeModule::PRIVATE); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0604.md b/src/librustc_error_codes/error_codes/E0604.md new file mode 100644 index 0000000000..adbf76509e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0604.md @@ -0,0 +1,19 @@ +A cast to `char` was attempted on a type other than `u8`. + +Erroneous code example: + +```compile_fail,E0604 +0u32 as char; // error: only `u8` can be cast as `char`, not `u32` +``` + +As the error message indicates, only `u8` can be cast into `char`. Example: + +``` +let c = 86u8 as char; // ok! +assert_eq!(c, 'V'); +``` + +For more information about casts, take a look at the Type cast section in +[The Reference Book][1]. + +[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions diff --git a/src/librustc_error_codes/error_codes/E0605.md b/src/librustc_error_codes/error_codes/E0605.md new file mode 100644 index 0000000000..f3cc65dd8c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0605.md @@ -0,0 +1,28 @@ +An invalid cast was attempted. + +Erroneous code examples: + +```compile_fail,E0605 +let x = 0u8; +x as Vec; // error: non-primitive cast: `u8` as `std::vec::Vec` + +// Another example + +let v = core::ptr::null::(); // So here, `v` is a `*const u8`. +v as &u8; // error: non-primitive cast: `*const u8` as `&u8` +``` + +Only primitive types can be cast into each other. Examples: + +``` +let x = 0u8; +x as u32; // ok! + +let v = core::ptr::null::(); +v as *const i8; // ok! +``` + +For more information about casts, take a look at the Type cast section in +[The Reference Book][1]. + +[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions diff --git a/src/librustc_error_codes/error_codes/E0606.md b/src/librustc_error_codes/error_codes/E0606.md new file mode 100644 index 0000000000..06ee7497fd --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0606.md @@ -0,0 +1,21 @@ +An incompatible cast was attempted. + +Erroneous code example: + +```compile_fail,E0606 +let x = &0u8; // Here, `x` is a `&u8`. +let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid +``` + +When casting, keep in mind that only primitive types can be cast into each +other. Example: + +``` +let x = &0u8; +let y: u32 = *x as u32; // We dereference it first and then cast it. +``` + +For more information about casts, take a look at the Type cast section in +[The Reference Book][1]. + +[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions diff --git a/src/librustc_error_codes/error_codes/E0607.md b/src/librustc_error_codes/error_codes/E0607.md new file mode 100644 index 0000000000..ea6e10105b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0607.md @@ -0,0 +1,26 @@ +A cast between a thin and a fat pointer was attempted. + +Erroneous code example: + +```compile_fail,E0607 +let v = core::ptr::null::(); +v as *const [u8]; +``` + +First: what are thin and fat pointers? + +Thin pointers are "simple" pointers: they are purely a reference to a memory +address. + +Fat pointers are pointers referencing Dynamically Sized Types (also called DST). +DST don't have a statically known size, therefore they can only exist behind +some kind of pointers that contain additional information. Slices and trait +objects are DSTs. In the case of slices, the additional information the fat +pointer holds is their size. + +To fix this error, don't try to cast directly between thin and fat pointers. + +For more information about casts, take a look at the Type cast section in +[The Reference Book][1]. + +[1]: https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions diff --git a/src/librustc_error_codes/error_codes/E0608.md b/src/librustc_error_codes/error_codes/E0608.md new file mode 100644 index 0000000000..598f1e655e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0608.md @@ -0,0 +1,18 @@ +An attempt to index into a type which doesn't implement the `std::ops::Index` +trait was performed. + +Erroneous code example: + +```compile_fail,E0608 +0u8[2]; // error: cannot index into a value of type `u8` +``` + +To be able to index into a type it needs to implement the `std::ops::Index` +trait. Example: + +``` +let v: Vec = vec![0, 1, 2, 3]; + +// The `Vec` type implements the `Index` trait so you can do: +println!("{}", v[2]); +``` diff --git a/src/librustc_error_codes/error_codes/E0609.md b/src/librustc_error_codes/error_codes/E0609.md new file mode 100644 index 0000000000..a9db34f474 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0609.md @@ -0,0 +1,24 @@ +Attempted to access a non-existent field in a struct. + +Erroneous code example: + +```compile_fail,E0609 +struct StructWithFields { + x: u32, +} + +let s = StructWithFields { x: 0 }; +println!("{}", s.foo); // error: no field `foo` on type `StructWithFields` +``` + +To fix this error, check that you didn't misspell the field's name or that the +field actually exists. Example: + +``` +struct StructWithFields { + x: u32, +} + +let s = StructWithFields { x: 0 }; +println!("{}", s.x); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0610.md b/src/librustc_error_codes/error_codes/E0610.md new file mode 100644 index 0000000000..d590ce51a3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0610.md @@ -0,0 +1,29 @@ +Attempted to access a field on a primitive type. + +Erroneous code example: + +```compile_fail,E0610 +let x: u32 = 0; +println!("{}", x.foo); // error: `{integer}` is a primitive type, therefore + // doesn't have fields +``` + +Primitive types are the most basic types available in Rust and don't have +fields. To access data via named fields, struct types are used. Example: + +``` +// We declare struct called `Foo` containing two fields: +struct Foo { + x: u32, + y: i64, +} + +// We create an instance of this struct: +let variable = Foo { x: 0, y: -12 }; +// And we can now access its fields: +println!("x: {}, y: {}", variable.x, variable.y); +``` + +For more information about primitives and structs, take a look at The Book: +https://doc.rust-lang.org/book/ch03-02-data-types.html +https://doc.rust-lang.org/book/ch05-00-structs.html diff --git a/src/librustc_error_codes/error_codes/E0614.md b/src/librustc_error_codes/error_codes/E0614.md new file mode 100644 index 0000000000..d0ed06ebce --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0614.md @@ -0,0 +1,18 @@ +Attempted to dereference a variable which cannot be dereferenced. + +Erroneous code example: + +```compile_fail,E0614 +let y = 0u32; +*y; // error: type `u32` cannot be dereferenced +``` + +Only types implementing `std::ops::Deref` can be dereferenced (such as `&T`). +Example: + +``` +let y = 0u32; +let x = &y; +// So here, `x` is a `&u32`, so we can dereference it: +*x; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0615.md b/src/librustc_error_codes/error_codes/E0615.md new file mode 100644 index 0000000000..f513d05962 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0615.md @@ -0,0 +1,35 @@ +Attempted to access a method like a field. + +Erroneous code example: + +```compile_fail,E0615 +struct Foo { + x: u32, +} + +impl Foo { + fn method(&self) {} +} + +let f = Foo { x: 0 }; +f.method; // error: attempted to take value of method `method` on type `Foo` +``` + +If you want to use a method, add `()` after it: + +``` +# struct Foo { x: u32 } +# impl Foo { fn method(&self) {} } +# let f = Foo { x: 0 }; +f.method(); +``` + +However, if you wanted to access a field of a struct check that the field name +is spelled correctly. Example: + +``` +# struct Foo { x: u32 } +# impl Foo { fn method(&self) {} } +# let f = Foo { x: 0 }; +println!("{}", f.x); +``` diff --git a/src/librustc_error_codes/error_codes/E0616.md b/src/librustc_error_codes/error_codes/E0616.md new file mode 100644 index 0000000000..5acbc6e44e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0616.md @@ -0,0 +1,57 @@ +Attempted to access a private field on a struct. + +Erroneous code example: + +```compile_fail,E0616 +mod some_module { + pub struct Foo { + x: u32, // So `x` is private in here. + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + } +} + +let f = some_module::Foo::new(); +println!("{}", f.x); // error: field `x` of struct `some_module::Foo` is private +``` + +If you want to access this field, you have two options: + +1) Set the field public: + +``` +mod some_module { + pub struct Foo { + pub x: u32, // `x` is now public. + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + } +} + +let f = some_module::Foo::new(); +println!("{}", f.x); // ok! +``` + +2) Add a getter function: + +``` +mod some_module { + pub struct Foo { + x: u32, // So `x` is still private in here. + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + + // We create the getter function here: + pub fn get_x(&self) -> &u32 { &self.x } + } +} + +let f = some_module::Foo::new(); +println!("{}", f.get_x()); // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0617.md b/src/librustc_error_codes/error_codes/E0617.md new file mode 100644 index 0000000000..f4357ff755 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0617.md @@ -0,0 +1,19 @@ +Attempted to pass an invalid type of variable into a variadic function. + +Erroneous code example: + +```compile_fail,E0617 +extern { + fn printf(c: *const i8, ...); +} + +unsafe { + printf(::std::ptr::null(), 0f32); + // error: cannot pass an `f32` to variadic function, cast to `c_double` +} +``` + +Certain Rust types must be cast before passing them to a variadic function, +because of arcane ABI rules dictated by the C standard. To fix the error, +cast the value to the type specified by the error message (which you may need +to import from `std::os::raw`). diff --git a/src/librustc_error_codes/error_codes/E0618.md b/src/librustc_error_codes/error_codes/E0618.md new file mode 100644 index 0000000000..c8dc9040cf --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0618.md @@ -0,0 +1,26 @@ +Attempted to call something which isn't a function nor a method. + +Erroneous code examples: + +```compile_fail,E0618 +enum X { + Entry, +} + +X::Entry(); // error: expected function, tuple struct or tuple variant, + // found `X::Entry` + +// Or even simpler: +let x = 0i32; +x(); // error: expected function, tuple struct or tuple variant, found `i32` +``` + +Only functions and methods can be called using `()`. Example: + +``` +// We declare a function: +fn i_am_a_function() {} + +// And we call it: +i_am_a_function(); +``` diff --git a/src/librustc_error_codes/error_codes/E0619.md b/src/librustc_error_codes/error_codes/E0619.md new file mode 100644 index 0000000000..8727692c0a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0619.md @@ -0,0 +1,38 @@ +#### Note: this error code is no longer emitted by the compiler. +The type-checker needed to know the type of an expression, but that type had not +yet been inferred. + +Erroneous code example: + +```compile_fail +let mut x = vec![]; +match x.pop() { + Some(v) => { + // Here, the type of `v` is not (yet) known, so we + // cannot resolve this method call: + v.to_uppercase(); // error: the type of this value must be known in + // this context + } + None => {} +} +``` + +Type inference typically proceeds from the top of the function to the bottom, +figuring out types as it goes. In some cases -- notably method calls and +overloadable operators like `*` -- the type checker may not have enough +information *yet* to make progress. This can be true even if the rest of the +function provides enough context (because the type-checker hasn't looked that +far ahead yet). In this case, type annotations can be used to help it along. + +To fix this error, just specify the type of the variable. Example: + +``` +let mut x: Vec = vec![]; // We precise the type of the vec elements. +match x.pop() { + Some(v) => { + v.to_uppercase(); // Since rustc now knows the type of the vec elements, + // we can use `v`'s methods. + } + None => {} +} +``` diff --git a/src/librustc_error_codes/error_codes/E0620.md b/src/librustc_error_codes/error_codes/E0620.md new file mode 100644 index 0000000000..f8e442807e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0620.md @@ -0,0 +1,18 @@ +A cast to an unsized type was attempted. + +Erroneous code example: + +```compile_fail,E0620 +let x = &[1_usize, 2] as [usize]; // error: cast to unsized type: `&[usize; 2]` + // as `[usize]` +``` + +In Rust, some types don't have a known size at compile-time. For example, in a +slice type like `[u32]`, the number of elements is not known at compile-time and +hence the overall size cannot be computed. As a result, such types can only be +manipulated through a reference (e.g., `&T` or `&mut T`) or other pointer-type +(e.g., `Box` or `Rc`). Try casting to a reference instead: + +``` +let x = &[1_usize, 2] as &[usize]; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0621.md b/src/librustc_error_codes/error_codes/E0621.md new file mode 100644 index 0000000000..7c0878df25 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0621.md @@ -0,0 +1,34 @@ +This error code indicates a mismatch between the lifetimes appearing in the +function signature (i.e., the parameter types and the return type) and the +data-flow found in the function body. + +Erroneous code example: + +```compile_fail,E0621 +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // error: explicit lifetime + // required in the type of + // `y` + if x > y { x } else { y } +} +``` + +In the code above, the function is returning data borrowed from either `x` or +`y`, but the `'a` annotation indicates that it is returning data only from `x`. +To fix the error, the signature and the body must be made to match. Typically, +this is done by updating the function signature. So, in this case, we change +the type of `y` to `&'a i32`, like so: + +``` +fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } +} +``` + +Now the signature indicates that the function data borrowed from either `x` or +`y`. Alternatively, you could change the body to not return data from `y`: + +``` +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + x +} +``` diff --git a/src/librustc_error_codes/error_codes/E0622.md b/src/librustc_error_codes/error_codes/E0622.md new file mode 100644 index 0000000000..1de81dabb2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0622.md @@ -0,0 +1,17 @@ +An intrinsic was declared without being a function. + +Erroneous code example: + +```compile_fail,E0622 +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + // error: intrinsic must be a function +} + +fn main() { unsafe { breakpoint(); } } +``` + +An intrinsic is a function available for use in a given programming language +whose implementation is handled specially by the compiler. In order to fix this +error, just declare a function. diff --git a/src/librustc_error_codes/error_codes/E0623.md b/src/librustc_error_codes/error_codes/E0623.md new file mode 100644 index 0000000000..1290edd0a0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0623.md @@ -0,0 +1,41 @@ +A lifetime didn't match what was expected. + +Erroneous code example: + +```compile_fail,E0623 +struct Foo<'a> { + x: &'a isize, +} + +fn bar<'short, 'long>(c: Foo<'short>, l: &'long isize) { + let _: Foo<'long> = c; // error! +} +``` + +In this example, we tried to set a value with an incompatible lifetime to +another one (`'long` is unrelated to `'short`). We can solve this issue in +two different ways: + +Either we make `'short` live at least as long as `'long`: + +``` +struct Foo<'a> { + x: &'a isize, +} + +// we set 'short to live at least as long as 'long +fn bar<'short: 'long, 'long>(c: Foo<'short>, l: &'long isize) { + let _: Foo<'long> = c; // ok! +} +``` + +Or we use only one lifetime: + +``` +struct Foo<'a> { + x: &'a isize, +} +fn bar<'short>(c: Foo<'short>, l: &'short isize) { + let _: Foo<'short> = c; // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0624.md b/src/librustc_error_codes/error_codes/E0624.md new file mode 100644 index 0000000000..0fd21c44b3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0624.md @@ -0,0 +1,53 @@ +A private item was used outside of its scope. + +Erroneous code example: + +```compile_fail,E0624 +mod inner { + pub struct Foo; + + impl Foo { + fn method(&self) {} + } +} + +let foo = inner::Foo; +foo.method(); // error: method `method` is private +``` + +Two possibilities are available to solve this issue: + +1. Only use the item in the scope it has been defined: + +``` +mod inner { + pub struct Foo; + + impl Foo { + fn method(&self) {} + } + + pub fn call_method(foo: &Foo) { // We create a public function. + foo.method(); // Which calls the item. + } +} + +let foo = inner::Foo; +inner::call_method(&foo); // And since the function is public, we can call the + // method through it. +``` + +2. Make the item public: + +``` +mod inner { + pub struct Foo; + + impl Foo { + pub fn method(&self) {} // It's now public. + } +} + +let foo = inner::Foo; +foo.method(); // Ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0626.md b/src/librustc_error_codes/error_codes/E0626.md new file mode 100644 index 0000000000..db50bd7ac4 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0626.md @@ -0,0 +1,90 @@ +This error occurs because a borrow in a generator persists across a +yield point. + +Erroneous code example: + +```compile_fail,E0626 +# #![feature(generators, generator_trait, pin)] +# use std::ops::Generator; +# use std::pin::Pin; +let mut b = || { + let a = &String::new(); // <-- This borrow... + yield (); // ...is still in scope here, when the yield occurs. + println!("{}", a); +}; +Pin::new(&mut b).resume(); +``` + +At present, it is not permitted to have a yield that occurs while a +borrow is still in scope. To resolve this error, the borrow must +either be "contained" to a smaller scope that does not overlap the +yield or else eliminated in another way. So, for example, we might +resolve the previous example by removing the borrow and just storing +the integer by value: + +``` +# #![feature(generators, generator_trait, pin)] +# use std::ops::Generator; +# use std::pin::Pin; +let mut b = || { + let a = 3; + yield (); + println!("{}", a); +}; +Pin::new(&mut b).resume(); +``` + +This is a very simple case, of course. In more complex cases, we may +wish to have more than one reference to the value that was borrowed -- +in those cases, something like the `Rc` or `Arc` types may be useful. + +This error also frequently arises with iteration: + +```compile_fail,E0626 +# #![feature(generators, generator_trait, pin)] +# use std::ops::Generator; +# use std::pin::Pin; +let mut b = || { + let v = vec![1,2,3]; + for &x in &v { // <-- borrow of `v` is still in scope... + yield x; // ...when this yield occurs. + } +}; +Pin::new(&mut b).resume(); +``` + +Such cases can sometimes be resolved by iterating "by value" (or using +`into_iter()`) to avoid borrowing: + +``` +# #![feature(generators, generator_trait, pin)] +# use std::ops::Generator; +# use std::pin::Pin; +let mut b = || { + let v = vec![1,2,3]; + for x in v { // <-- Take ownership of the values instead! + yield x; // <-- Now yield is OK. + } +}; +Pin::new(&mut b).resume(); +``` + +If taking ownership is not an option, using indices can work too: + +``` +# #![feature(generators, generator_trait, pin)] +# use std::ops::Generator; +# use std::pin::Pin; +let mut b = || { + let v = vec![1,2,3]; + let len = v.len(); // (*) + for i in 0..len { + let x = v[i]; // (*) + yield x; // <-- Now yield is OK. + } +}; +Pin::new(&mut b).resume(); + +// (*) -- Unfortunately, these temporaries are currently required. +// See . +``` diff --git a/src/librustc_error_codes/error_codes/E0631.md b/src/librustc_error_codes/error_codes/E0631.md new file mode 100644 index 0000000000..6188d5f61a --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0631.md @@ -0,0 +1,27 @@ +This error indicates a type mismatch in closure arguments. + +Erroneous code example: + +```compile_fail,E0631 +fn foo(f: F) { +} + +fn main() { + foo(|x: &str| {}); +} +``` + +The error occurs because `foo` accepts a closure that takes an `i32` argument, +but in `main`, it is passed a closure with a `&str` argument. + +This can be resolved by changing the type annotation or removing it entirely +if it can be inferred. + +``` +fn foo(f: F) { +} + +fn main() { + foo(|x: i32| {}); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0633.md b/src/librustc_error_codes/error_codes/E0633.md new file mode 100644 index 0000000000..65cdf90036 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0633.md @@ -0,0 +1,23 @@ +The `unwind` attribute was malformed. + +Erroneous code example: + +```ignore (compile_fail not working here; see Issue #43707) +#[unwind()] // error: expected one argument +pub extern fn something() {} + +fn main() {} +``` + +The `#[unwind]` attribute should be used as follows: + +- `#[unwind(aborts)]` -- specifies that if a non-Rust ABI function + should abort the process if it attempts to unwind. This is the safer + and preferred option. + +- `#[unwind(allowed)]` -- specifies that a non-Rust ABI function + should be allowed to unwind. This can easily result in Undefined + Behavior (UB), so be careful. + +NB. The default behavior here is "allowed", but this is unspecified +and likely to change in the future. diff --git a/src/librustc_error_codes/error_codes/E0635.md b/src/librustc_error_codes/error_codes/E0635.md new file mode 100644 index 0000000000..a39d2be4f8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0635.md @@ -0,0 +1,7 @@ +The `#![feature]` attribute specified an unknown feature. + +Erroneous code example: + +```compile_fail,E0635 +#![feature(nonexistent_rust_feature)] // error: unknown feature +``` diff --git a/src/librustc_error_codes/error_codes/E0636.md b/src/librustc_error_codes/error_codes/E0636.md new file mode 100644 index 0000000000..57cf72db55 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0636.md @@ -0,0 +1,9 @@ +A `#![feature]` attribute was declared multiple times. + +Erroneous code example: + +```compile_fail,E0636 +#![allow(stable_features)] +#![feature(rust1)] +#![feature(rust1)] // error: the feature `rust1` has already been declared +``` diff --git a/src/librustc_error_codes/error_codes/E0638.md b/src/librustc_error_codes/error_codes/E0638.md new file mode 100644 index 0000000000..29b7586b07 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0638.md @@ -0,0 +1,47 @@ +This error indicates that the struct, enum or enum variant must be matched +non-exhaustively as it has been marked as `non_exhaustive`. + +When applied within a crate, downstream users of the crate will need to use the +`_` pattern when matching enums and use the `..` pattern when matching structs. +Downstream crates cannot match against non-exhaustive enum variants. + +For example, in the below example, since the enum is marked as +`non_exhaustive`, it is required that downstream crates match non-exhaustively +on it. + +```rust,ignore (pseudo-Rust) +use std::error::Error as StdError; + +#[non_exhaustive] pub enum Error { + Message(String), + Other, +} + +impl StdError for Error { + fn description(&self) -> &str { + // This will not error, despite being marked as non_exhaustive, as this + // enum is defined within the current crate, it can be matched + // exhaustively. + match *self { + Message(ref s) => s, + Other => "other or unknown error", + } + } +} +``` + +An example of matching non-exhaustively on the above enum is provided below: + +```rust,ignore (pseudo-Rust) +use mycrate::Error; + +// This will not error as the non_exhaustive Error enum has been matched with a +// wildcard. +match error { + Message(ref s) => ..., + Other => ..., + _ => ..., +} +``` + +Similarly, for structs, match with `..` to avoid this error. diff --git a/src/librustc_error_codes/error_codes/E0639.md b/src/librustc_error_codes/error_codes/E0639.md new file mode 100644 index 0000000000..c2d9662337 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0639.md @@ -0,0 +1,7 @@ +This error indicates that the struct, enum or enum variant cannot be +instantiated from outside of the defining crate as it has been marked +as `non_exhaustive` and as such more fields/variants may be added in +future that could cause adverse side effects for this code. + +It is recommended that you look for a `new` function or equivalent in the +crate's documentation. diff --git a/src/librustc_error_codes/error_codes/E0641.md b/src/librustc_error_codes/error_codes/E0641.md new file mode 100644 index 0000000000..e2110042c7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0641.md @@ -0,0 +1,19 @@ +Attempted to cast to/from a pointer with an unknown kind. + +Erroneous code examples: + +```compile_fail,E0641 +let b = 0 as *const _; // error +``` + +Must give information for type of pointer that is being cast from/to if the +type cannot be inferred. + +``` +// Creating a pointer from reference: type can be inferred +let a = &(String::from("Hello world!")) as *const _; // Ok + +let b = 0 as *const i32; // Ok + +let c: *const i32 = 0 as *const _; // Ok +``` diff --git a/src/librustc_error_codes/error_codes/E0642.md b/src/librustc_error_codes/error_codes/E0642.md new file mode 100644 index 0000000000..592ada6eca --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0642.md @@ -0,0 +1,18 @@ +Trait methods currently cannot take patterns as arguments. + +Example of erroneous code: + +```compile_fail,E0642 +trait Foo { + fn foo((x, y): (i32, i32)); // error: patterns aren't allowed + // in trait methods +} +``` + +You can instead use a single name for the argument: + +``` +trait Foo { + fn foo(x_and_y: (i32, i32)); // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0643.md b/src/librustc_error_codes/error_codes/E0643.md new file mode 100644 index 0000000000..53919607df --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0643.md @@ -0,0 +1,12 @@ +This error indicates that there is a mismatch between generic parameters and +impl Trait parameters in a trait declaration versus its impl. + +```compile_fail,E0643 +trait Foo { + fn foo(&self, _: &impl Iterator); +} +impl Foo for () { + fn foo(&self, _: &U) { } // error method `foo` has incompatible + // signature for trait +} +``` diff --git a/src/librustc_error_codes/error_codes/E0644.md b/src/librustc_error_codes/error_codes/E0644.md new file mode 100644 index 0000000000..7a653bd226 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0644.md @@ -0,0 +1,29 @@ +A closure or generator was constructed that references its own type. + +Erroneous example: + +```compile-fail,E0644 +fn fix(f: &F) + where F: Fn(&F) +{ + f(&f); +} + +fn main() { + fix(&|y| { + // Here, when `x` is called, the parameter `y` is equal to `x`. + }); +} +``` + +Rust does not permit a closure to directly reference its own type, +either through an argument (as in the example above) or by capturing +itself through its environment. This restriction helps keep closure +inference tractable. + +The easiest fix is to rewrite your closure into a top-level function, +or into a method. In some cases, you may also be able to have your +closure call itself by capturing a `&Fn()` object or `fn()` pointer +that refers to itself. That is permitting, since the closure would be +invoking itself via a virtual call, and hence does not directly +reference its own *type*. diff --git a/src/librustc_error_codes/error_codes/E0646.md b/src/librustc_error_codes/error_codes/E0646.md new file mode 100644 index 0000000000..e01dbae8b9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0646.md @@ -0,0 +1,8 @@ +It is not possible to define `main` with a where clause. +Erroneous code example: + +```compile_fail,E0646 +fn main() where i32: Copy { // error: main function is not allowed to have + // a where clause +} +``` diff --git a/src/librustc_error_codes/error_codes/E0647.md b/src/librustc_error_codes/error_codes/E0647.md new file mode 100644 index 0000000000..131db38c00 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0647.md @@ -0,0 +1,12 @@ +It is not possible to define `start` with a where clause. +Erroneous code example: + +```compile_fail,E0647 +#![feature(start)] + +#[start] +fn start(_: isize, _: *const *const u8) -> isize where (): Copy { + //^ error: start function is not allowed to have a where clause + 0 +} +``` diff --git a/src/librustc_error_codes/error_codes/E0648.md b/src/librustc_error_codes/error_codes/E0648.md new file mode 100644 index 0000000000..319bae103f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0648.md @@ -0,0 +1,6 @@ +`export_name` attributes may not contain null characters (`\0`). + +```compile_fail,E0648 +#[export_name="\0foo"] // error: `export_name` may not contain null characters +pub fn bar() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0658.md b/src/librustc_error_codes/error_codes/E0658.md new file mode 100644 index 0000000000..44a38cee23 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0658.md @@ -0,0 +1,26 @@ +An unstable feature was used. + +Erroneous code example: + +```compile_fail,E658 +#[repr(u128)] // error: use of unstable library feature 'repr128' +enum Foo { + Bar(u64), +} +``` + +If you're using a stable or a beta version of rustc, you won't be able to use +any unstable features. In order to do so, please switch to a nightly version of +rustc (by using rustup). + +If you're using a nightly version of rustc, just add the corresponding feature +to be able to use it: + +``` +#![feature(repr128)] + +#[repr(u128)] // ok! +enum Foo { + Bar(u64), +} +``` diff --git a/src/librustc_error_codes/error_codes/E0659.md b/src/librustc_error_codes/error_codes/E0659.md new file mode 100644 index 0000000000..e2c7e25cc8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0659.md @@ -0,0 +1,50 @@ +An item usage is ambiguous. + +Erroneous code example: + +```compile_fail,edition2018,E0659 +pub mod moon { + pub fn foo() {} +} + +pub mod earth { + pub fn foo() {} +} + +mod collider { + pub use crate::moon::*; + pub use crate::earth::*; +} + +fn main() { + crate::collider::foo(); // ERROR: `foo` is ambiguous +} +``` + +This error generally appears when two items with the same name are imported into +a module. Here, the `foo` functions are imported and reexported from the +`collider` module and therefore, when we're using `collider::foo()`, both +functions collide. + +To solve this error, the best solution is generally to keep the path before the +item when using it. Example: + +```edition2018 +pub mod moon { + pub fn foo() {} +} + +pub mod earth { + pub fn foo() {} +} + +mod collider { + pub use crate::moon; + pub use crate::earth; +} + +fn main() { + crate::collider::moon::foo(); // ok! + crate::collider::earth::foo(); // ok! +} +``` diff --git a/src/librustc_error_codes/error_codes/E0660.md b/src/librustc_error_codes/error_codes/E0660.md new file mode 100644 index 0000000000..bceab1e005 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0660.md @@ -0,0 +1,11 @@ +The argument to the `asm` macro is not well-formed. + +Erroneous code example: + +```compile_fail,E0660 +asm!("nop" "nop"); +``` + +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0661.md b/src/librustc_error_codes/error_codes/E0661.md new file mode 100644 index 0000000000..9979a61ee9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0661.md @@ -0,0 +1,12 @@ +An invalid syntax was passed to the second argument of an `asm` macro line. + +Erroneous code example: + +```compile_fail,E0661 +let a; +asm!("nop" : "r"(a)); +``` + +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0662.md b/src/librustc_error_codes/error_codes/E0662.md new file mode 100644 index 0000000000..3ba00eaab5 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0662.md @@ -0,0 +1,14 @@ +An invalid input operand constraint was passed to the `asm` macro (third line). + +Erroneous code example: + +```compile_fail,E0662 +asm!("xor %eax, %eax" + : + : "=test"("a") + ); +``` + +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0663.md b/src/librustc_error_codes/error_codes/E0663.md new file mode 100644 index 0000000000..be121aa0b7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0663.md @@ -0,0 +1,14 @@ +An invalid input operand constraint was passed to the `asm` macro (third line). + +Erroneous code example: + +```compile_fail,E0663 +asm!("xor %eax, %eax" + : + : "+test"("a") + ); +``` + +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0664.md b/src/librustc_error_codes/error_codes/E0664.md new file mode 100644 index 0000000000..2b9546453d --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0664.md @@ -0,0 +1,15 @@ +A clobber was surrounded by braces in the `asm` macro. + +Erroneous code example: + +```compile_fail,E0664 +asm!("mov $$0x200, %eax" + : + : + : "{eax}" + ); +``` + +Considering that this would be a long explanation, we instead recommend you to +take a look at the unstable book: +https://doc.rust-lang.org/unstable-book/language-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0665.md b/src/librustc_error_codes/error_codes/E0665.md new file mode 100644 index 0000000000..a15f4021c7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0665.md @@ -0,0 +1,31 @@ +The `Default` trait was derived on an enum. + +Erroneous code example: + +```compile_fail,E0665 +#[derive(Default)] +enum Food { + Sweet, + Salty, +} +``` + +The `Default` cannot be derived on an enum for the simple reason that the +compiler doesn't know which value to pick by default whereas it can for a +struct as long as all its fields implement the `Default` trait as well. + +If you still want to implement `Default` on your enum, you'll have to do it "by +hand": + +``` +enum Food { + Sweet, + Salty, +} + +impl Default for Food { + fn default() -> Food { + Food::Sweet + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0666.md b/src/librustc_error_codes/error_codes/E0666.md new file mode 100644 index 0000000000..22133683dc --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0666.md @@ -0,0 +1,21 @@ +`impl Trait` types cannot appear nested in the +generic arguments of other `impl Trait` types. + +Example of erroneous code: + +```compile_fail,E0666 +trait MyGenericTrait {} +trait MyInnerTrait {} + +fn foo(bar: impl MyGenericTrait) {} +``` + +Type parameters for `impl Trait` types must be +explicitly defined as named generic parameters: + +``` +trait MyGenericTrait {} +trait MyInnerTrait {} + +fn foo(bar: impl MyGenericTrait) {} +``` diff --git a/src/librustc_error_codes/error_codes/E0668.md b/src/librustc_error_codes/error_codes/E0668.md new file mode 100644 index 0000000000..2621a31a9e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0668.md @@ -0,0 +1,19 @@ +Malformed inline assembly rejected by LLVM. + +LLVM checks the validity of the constraints and the assembly string passed to +it. This error implies that LLVM seems something wrong with the inline +assembly call. + +In particular, it can happen if you forgot the closing bracket of a register +constraint (see issue #51430): +```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) +#![feature(asm)] + +fn main() { + let rax: u64; + unsafe { + asm!("" :"={rax"(rax)); + println!("Accumulator is: {}", rax); + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0669.md b/src/librustc_error_codes/error_codes/E0669.md new file mode 100644 index 0000000000..39de01eebe --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0669.md @@ -0,0 +1,8 @@ +Cannot convert inline assembly operand to a single LLVM value. + +This error usually happens when trying to pass in a value to an input inline +assembly operand that is actually a pair of values. In particular, this can +happen when trying to pass in a slice, for instance a `&str`. In Rust, these +values are represented internally as a pair of values, the pointer and its +length. When passed as an input operand, this pair of values can not be +coerced into a register and thus we must fail with an error. diff --git a/src/librustc_error_codes/error_codes/E0670.md b/src/librustc_error_codes/error_codes/E0670.md new file mode 100644 index 0000000000..2026370bec --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0670.md @@ -0,0 +1,9 @@ +Rust 2015 does not permit the use of `async fn`. + +Example of erroneous code: + +```compile_fail,E0670 +async fn foo() {} +``` + +Switch to the Rust 2018 edition to use `async fn`. diff --git a/src/librustc_error_codes/error_codes/E0671.md b/src/librustc_error_codes/error_codes/E0671.md new file mode 100644 index 0000000000..449fb8ffc8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0671.md @@ -0,0 +1,12 @@ +#### Note: this error code is no longer emitted by the compiler. + +Const parameters cannot depend on type parameters. +The following is therefore invalid: + +```compile_fail,E0741 +#![feature(const_generics)] + +fn const_id() -> T { // error + N +} +``` diff --git a/src/librustc_error_codes/error_codes/E0689.md b/src/librustc_error_codes/error_codes/E0689.md new file mode 100644 index 0000000000..26c2c15ccf --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0689.md @@ -0,0 +1,26 @@ +This error indicates that the numeric value for the method being passed exists +but the type of the numeric value or binding could not be identified. + +The error happens on numeric literals: + +```compile_fail,E0689 +2.0.neg(); +``` + +and on numeric bindings without an identified concrete type: + +```compile_fail,E0689 +let x = 2.0; +x.neg(); // same error as above +``` + +Because of this, you must give the numeric literal or binding a type: + +``` +use std::ops::Neg; + +let _ = 2.0_f32.neg(); +let x: f32 = 2.0; +let _ = x.neg(); +let _ = (2.0 as f32).neg(); +``` diff --git a/src/librustc_error_codes/error_codes/E0690.md b/src/librustc_error_codes/error_codes/E0690.md new file mode 100644 index 0000000000..3a4d1c56fa --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0690.md @@ -0,0 +1,33 @@ +A struct with the representation hint `repr(transparent)` had zero or more than +one fields that were not guaranteed to be zero-sized. + +Erroneous code example: + +```compile_fail,E0690 +#[repr(transparent)] +struct LengthWithUnit { // error: transparent struct needs exactly one + value: f32, // non-zero-sized field, but has 2 + unit: U, +} +``` + +Because transparent structs are represented exactly like one of their fields at +run time, said field must be uniquely determined. If there is no field, or if +there are multiple fields, it is not clear how the struct should be represented. +Note that fields of zero-typed types (e.g., `PhantomData`) can also exist +alongside the field that contains the actual data, they do not count for this +error. When generic types are involved (as in the above example), an error is +reported because the type parameter could be non-zero-sized. + +To combine `repr(transparent)` with type parameters, `PhantomData` may be +useful: + +``` +use std::marker::PhantomData; + +#[repr(transparent)] +struct LengthWithUnit { + value: f32, + unit: PhantomData, +} +``` diff --git a/src/librustc_error_codes/error_codes/E0691.md b/src/librustc_error_codes/error_codes/E0691.md new file mode 100644 index 0000000000..60060cacbd --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0691.md @@ -0,0 +1,48 @@ +A struct, enum, or union with the `repr(transparent)` representation hint +contains a zero-sized field that requires non-trivial alignment. + +Erroneous code example: + +```compile_fail,E0691 +#![feature(repr_align)] + +#[repr(align(32))] +struct ForceAlign32; + +#[repr(transparent)] +struct Wrapper(f32, ForceAlign32); // error: zero-sized field in transparent + // struct has alignment larger than 1 +``` + +A transparent struct, enum, or union is supposed to be represented exactly like +the piece of data it contains. Zero-sized fields with different alignment +requirements potentially conflict with this property. In the example above, +`Wrapper` would have to be aligned to 32 bytes even though `f32` has a smaller +alignment requirement. + +Consider removing the over-aligned zero-sized field: + +``` +#[repr(transparent)] +struct Wrapper(f32); +``` + +Alternatively, `PhantomData` has alignment 1 for all `T`, so you can use it +if you need to keep the field for some reason: + +``` +#![feature(repr_align)] + +use std::marker::PhantomData; + +#[repr(align(32))] +struct ForceAlign32; + +#[repr(transparent)] +struct Wrapper(f32, PhantomData); +``` + +Note that empty arrays `[T; 0]` have the same alignment requirement as the +element type `T`. Also note that the error is conservatively reported even when +the alignment of the zero-sized type is less than or equal to the data field's +alignment. diff --git a/src/librustc_error_codes/error_codes/E0692.md b/src/librustc_error_codes/error_codes/E0692.md new file mode 100644 index 0000000000..596cb1e777 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0692.md @@ -0,0 +1,49 @@ +A `repr(transparent)` type was also annotated with other, incompatible +representation hints. + +Erroneous code example: + +```compile_fail,E0692 +#[repr(transparent, C)] // error: incompatible representation hints +struct Grams(f32); +``` + +A type annotated as `repr(transparent)` delegates all representation concerns to +another type, so adding more representation hints is contradictory. Remove +either the `transparent` hint or the other hints, like this: + +``` +#[repr(transparent)] +struct Grams(f32); +``` + +Alternatively, move the other attributes to the contained type: + +``` +#[repr(C)] +struct Foo { + x: i32, + // ... +} + +#[repr(transparent)] +struct FooWrapper(Foo); +``` + +Note that introducing another `struct` just to have a place for the other +attributes may have unintended side effects on the representation: + +``` +#[repr(transparent)] +struct Grams(f32); + +#[repr(C)] +struct Float(f32); + +#[repr(transparent)] +struct Grams2(Float); // this is not equivalent to `Grams` above +``` + +Here, `Grams2` is a not equivalent to `Grams` -- the former transparently wraps +a (non-transparent) struct containing a single float, while `Grams` is a +transparent wrapper around a float. This can make a difference for the ABI. diff --git a/src/librustc_error_codes/error_codes/E0695.md b/src/librustc_error_codes/error_codes/E0695.md new file mode 100644 index 0000000000..208f7f4c7b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0695.md @@ -0,0 +1,35 @@ +A `break` statement without a label appeared inside a labeled block. + +Example of erroneous code: + +```compile_fail,E0695 +# #![feature(label_break_value)] +loop { + 'a: { + break; + } +} +``` + +Make sure to always label the `break`: + +``` +# #![feature(label_break_value)] +'l: loop { + 'a: { + break 'l; + } +} +``` + +Or if you want to `break` the labeled block: + +``` +# #![feature(label_break_value)] +loop { + 'a: { + break 'a; + } + break; +} +``` diff --git a/src/librustc_error_codes/error_codes/E0697.md b/src/librustc_error_codes/error_codes/E0697.md new file mode 100644 index 0000000000..ab63d2e73f --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0697.md @@ -0,0 +1,15 @@ +A closure has been used as `static`. + +Erroneous code example: + +```compile_fail,E0697 +fn main() { + static || {}; // used as `static` +} +``` + +Closures cannot be used as `static`. They "save" the environment, +and as such a static closure would save only a static environment +which would consist only of variables with a static lifetime. Given +this it would be better to use a proper function. The easiest fix +is to remove the `static` keyword. diff --git a/src/librustc_error_codes/error_codes/E0698.md b/src/librustc_error_codes/error_codes/E0698.md new file mode 100644 index 0000000000..d0fcec3990 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0698.md @@ -0,0 +1,25 @@ +When using generators (or async) all type variables must be bound so a +generator can be constructed. + +Erroneous code example: + +```edition2018,compile-fail,E0698 +async fn bar() -> () {} + +async fn foo() { + bar().await; // error: cannot infer type for `T` +} +``` + +In the above example `T` is unknowable by the compiler. +To fix this you must bind `T` to a concrete type such as `String` +so that a generator can then be constructed: + +```edition2018 +async fn bar() -> () {} + +async fn foo() { + bar::().await; + // ^^^^^^^^ specify type explicitly +} +``` diff --git a/src/librustc_error_codes/error_codes/E0699.md b/src/librustc_error_codes/error_codes/E0699.md new file mode 100644 index 0000000000..f90fd3b562 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0699.md @@ -0,0 +1,44 @@ +A method was called on a raw pointer whose inner type wasn't completely known. + +For example, you may have done something like: + +```compile_fail +# #![deny(warnings)] +let foo = &1; +let bar = foo as *const _; +if bar.is_null() { + // ... +} +``` + +Here, the type of `bar` isn't known; it could be a pointer to anything. Instead, +specify a type for the pointer (preferably something that makes sense for the +thing you're pointing to): + +``` +let foo = &1; +let bar = foo as *const i32; +if bar.is_null() { + // ... +} +``` + +Even though `is_null()` exists as a method on any raw pointer, Rust shows this +error because Rust allows for `self` to have arbitrary types (behind the +arbitrary_self_types feature flag). + +This means that someone can specify such a function: + +```ignore (cannot-doctest-feature-doesnt-exist-yet) +impl Foo { + fn is_null(self: *const Self) -> bool { + // do something else + } +} +``` + +and now when you call `.is_null()` on a raw pointer to `Foo`, there's ambiguity. + +Given that we don't know what type the pointer is, and there's potential +ambiguity for some types, we disallow calling methods on raw pointers when +the type is unknown. diff --git a/src/librustc_error_codes/error_codes/E0700.md b/src/librustc_error_codes/error_codes/E0700.md new file mode 100644 index 0000000000..41ac4d948c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0700.md @@ -0,0 +1,44 @@ +The `impl Trait` return type captures lifetime parameters that do not +appear within the `impl Trait` itself. + +Erroneous code example: + +```compile-fail,E0700 +use std::cell::Cell; + +trait Trait<'a> { } + +impl<'a, 'b> Trait<'b> for Cell<&'a u32> { } + +fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> +where 'x: 'y +{ + x +} +``` + +Here, the function `foo` returns a value of type `Cell<&'x u32>`, +which references the lifetime `'x`. However, the return type is +declared as `impl Trait<'y>` -- this indicates that `foo` returns +"some type that implements `Trait<'y>`", but it also indicates that +the return type **only captures data referencing the lifetime `'y`**. +In this case, though, we are referencing data with lifetime `'x`, so +this function is in error. + +To fix this, you must reference the lifetime `'x` from the return +type. For example, changing the return type to `impl Trait<'y> + 'x` +would work: + +``` +use std::cell::Cell; + +trait Trait<'a> { } + +impl<'a,'b> Trait<'b> for Cell<&'a u32> { } + +fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x +where 'x: 'y +{ + x +} +``` diff --git a/src/librustc_error_codes/error_codes/E0701.md b/src/librustc_error_codes/error_codes/E0701.md new file mode 100644 index 0000000000..87f416ada1 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0701.md @@ -0,0 +1,9 @@ +This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed +on something other than a struct or enum. + +Examples of erroneous code: + +```compile_fail,E0701 +#[non_exhaustive] +trait Foo { } +``` diff --git a/src/librustc_error_codes/error_codes/E0704.md b/src/librustc_error_codes/error_codes/E0704.md new file mode 100644 index 0000000000..cde46f52c2 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0704.md @@ -0,0 +1,26 @@ +This error indicates that a incorrect visibility restriction was specified. + +Example of erroneous code: + +```compile_fail,E0704 +mod foo { + pub(foo) struct Bar { + x: i32 + } +} +``` + +To make struct `Bar` only visible in module `foo` the `in` keyword should be +used: +``` +mod foo { + pub(in crate::foo) struct Bar { + x: i32 + } +} +# fn main() {} +``` + +For more information see the Rust Reference on [Visibility]. + +[Visibility]: https://doc.rust-lang.org/reference/visibility-and-privacy.html diff --git a/src/librustc_error_codes/error_codes/E0705.md b/src/librustc_error_codes/error_codes/E0705.md new file mode 100644 index 0000000000..8fa09fe8e7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0705.md @@ -0,0 +1,11 @@ +A `#![feature]` attribute was declared for a feature that is stable in +the current edition, but not in all editions. + +Erroneous code example: + +```ignore (limited to a warning during 2018 edition development) +#![feature(rust_2018_preview)] +#![feature(test_2018_feature)] // error: the feature + // `test_2018_feature` is + // included in the Rust 2018 edition +``` diff --git a/src/librustc_error_codes/error_codes/E0706.md b/src/librustc_error_codes/error_codes/E0706.md new file mode 100644 index 0000000000..d379b8a238 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0706.md @@ -0,0 +1,59 @@ +`async fn`s are not yet supported in traits in Rust. + +Erroneous code example: + +```compile_fail,edition2018 +trait T { + // Neither case is currently supported. + async fn foo() {} + async fn bar(&self) {} +} +``` + +`async fn`s return an `impl Future`, making the following two examples +equivalent: + +```edition2018,ignore (example-of-desugaring-equivalence) +async fn foo() -> User { + unimplemented!() +} +// The async fn above gets desugared as follows: +fn foo(&self) -> impl Future + '_ { + unimplemented!() +} +``` + +But when it comes to supporting this in traits, there are [a few implementation +issues][async-is-hard]. One of them is returning `impl Trait` in traits is not +supported, as it would require [Generic Associated Types] to be supported: + +```edition2018,ignore (example-of-desugaring-equivalence) +impl MyDatabase { + async fn get_user(&self) -> User { + unimplemented!() + } +} + +impl MyDatabase { + fn get_user(&self) -> impl Future + '_ { + unimplemented!() + } +} +``` + +Until these issues are resolved, you can use the [`async-trait` crate], allowing +you to use `async fn` in traits by desugaring to "boxed futures" +(`Pin>`). + +Note that using these trait methods will result in a heap allocation +per-function-call. This is not a significant cost for the vast majority of +applications, but should be considered when deciding whether to use this +functionality in the public API of a low-level function that is expected to be +called millions of times a second. + +You might be interested in visiting the [async book] for further information. + +[`async-trait` crate]: https://crates.io/crates/async-trait +[async-is-hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/ +[Generic Associated Types]: https://github.com/rust-lang/rust/issues/44265 +[async book]: https://rust-lang.github.io/async-book/07_workarounds/06_async_in_traits.html diff --git a/src/librustc_error_codes/error_codes/E0712.md b/src/librustc_error_codes/error_codes/E0712.md new file mode 100644 index 0000000000..89f60084f0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0712.md @@ -0,0 +1,19 @@ +This error occurs because a borrow of a thread-local variable was made inside a +function which outlived the lifetime of the function. + +Erroneous code example: + +```compile_fail,E0712 +#![feature(thread_local)] + +#[thread_local] +static FOO: u8 = 3; + +fn main() { + let a = &FOO; // error: thread-local variable borrowed past end of function + + std::thread::spawn(move || { + println!("{}", a); + }); +} +``` diff --git a/src/librustc_error_codes/error_codes/E0713.md b/src/librustc_error_codes/error_codes/E0713.md new file mode 100644 index 0000000000..9361046943 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0713.md @@ -0,0 +1,51 @@ +This error occurs when an attempt is made to borrow state past the end of the +lifetime of a type that implements the `Drop` trait. + +Erroneous code example: + +```compile_fail,E0713 +#![feature(nll)] + +pub struct S<'a> { data: &'a mut String } + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { self.data.push_str("being dropped"); } +} + +fn demo<'a>(s: S<'a>) -> &'a mut String { let p = &mut *s.data; p } +``` + +Here, `demo` tries to borrow the string data held within its +argument `s` and then return that borrow. However, `S` is +declared as implementing `Drop`. + +Structs implementing the `Drop` trait have an implicit destructor that +gets called when they go out of scope. This destructor gets exclusive +access to the fields of the struct when it runs. + +This means that when `s` reaches the end of `demo`, its destructor +gets exclusive access to its `&mut`-borrowed string data. allowing +another borrow of that string data (`p`), to exist across the drop of +`s` would be a violation of the principle that `&mut`-borrows have +exclusive, unaliased access to their referenced data. + +This error can be fixed by changing `demo` so that the destructor does +not run while the string-data is borrowed; for example by taking `S` +by reference: + +``` +pub struct S<'a> { data: &'a mut String } + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { self.data.push_str("being dropped"); } +} + +fn demo<'a>(s: &'a mut S<'a>) -> &'a mut String { let p = &mut *(*s).data; p } +``` + +Note that this approach needs a reference to S with lifetime `'a`. +Nothing shorter than `'a` will suffice: a shorter lifetime would imply +that after `demo` finishes executing, something else (such as the +destructor!) could access `s.data` after the end of that shorter +lifetime, which would again violate the `&mut`-borrow's exclusive +access. diff --git a/src/librustc_error_codes/error_codes/E0714.md b/src/librustc_error_codes/error_codes/E0714.md new file mode 100644 index 0000000000..e8707f3e39 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0714.md @@ -0,0 +1,5 @@ +A `#[marker]` trait contained an associated item. + +The items of marker traits cannot be overridden, so there's no need to have them +when they cannot be changed per-type anyway. If you wanted them for ergonomic +reasons, consider making an extension trait instead. diff --git a/src/librustc_error_codes/error_codes/E0715.md b/src/librustc_error_codes/error_codes/E0715.md new file mode 100644 index 0000000000..9e20e81368 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0715.md @@ -0,0 +1,5 @@ +An `impl` for a `#[marker]` trait tried to override an associated item. + +Because marker traits are allowed to have multiple implementations for the same +type, it's not allowed to override anything in those implementations, as it +would be ambiguous which override should actually be used. diff --git a/src/librustc_error_codes/error_codes/E0716.md b/src/librustc_error_codes/error_codes/E0716.md new file mode 100644 index 0000000000..25567c1d12 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0716.md @@ -0,0 +1,82 @@ +This error indicates that a temporary value is being dropped +while a borrow is still in active use. + +Erroneous code example: + +```compile_fail,E0716 +fn foo() -> i32 { 22 } +fn bar(x: &i32) -> &i32 { x } +let p = bar(&foo()); + // ------ creates a temporary +let q = *p; +``` + +Here, the expression `&foo()` is borrowing the expression +`foo()`. As `foo()` is a call to a function, and not the name of +a variable, this creates a **temporary** -- that temporary stores +the return value from `foo()` so that it can be borrowed. +You could imagine that `let p = bar(&foo());` is equivalent +to this: + +```compile_fail,E0597 +# fn foo() -> i32 { 22 } +# fn bar(x: &i32) -> &i32 { x } +let p = { + let tmp = foo(); // the temporary + bar(&tmp) +}; // <-- tmp is freed as we exit this block +let q = p; +``` + +Whenever a temporary is created, it is automatically dropped (freed) +according to fixed rules. Ordinarily, the temporary is dropped +at the end of the enclosing statement -- in this case, after the `let`. +This is illustrated in the example above by showing that `tmp` would +be freed as we exit the block. + +To fix this problem, you need to create a local variable +to store the value in rather than relying on a temporary. +For example, you might change the original program to +the following: + +``` +fn foo() -> i32 { 22 } +fn bar(x: &i32) -> &i32 { x } +let value = foo(); // dropped at the end of the enclosing block +let p = bar(&value); +let q = *p; +``` + +By introducing the explicit `let value`, we allocate storage +that will last until the end of the enclosing block (when `value` +goes out of scope). When we borrow `&value`, we are borrowing a +local variable that already exists, and hence no temporary is created. + +Temporaries are not always dropped at the end of the enclosing +statement. In simple cases where the `&` expression is immediately +stored into a variable, the compiler will automatically extend +the lifetime of the temporary until the end of the enclosing +block. Therefore, an alternative way to fix the original +program is to write `let tmp = &foo()` and not `let tmp = foo()`: + +``` +fn foo() -> i32 { 22 } +fn bar(x: &i32) -> &i32 { x } +let value = &foo(); +let p = bar(value); +let q = *p; +``` + +Here, we are still borrowing `foo()`, but as the borrow is assigned +directly into a variable, the temporary will not be dropped until +the end of the enclosing block. Similar rules apply when temporaries +are stored into aggregate structures like a tuple or struct: + +``` +// Here, two temporaries are created, but +// as they are stored directly into `value`, +// they are not dropped until the end of the +// enclosing block. +fn foo() -> i32 { 22 } +let value = (&foo(), &foo()); +``` diff --git a/src/librustc_error_codes/error_codes/E0718.md b/src/librustc_error_codes/error_codes/E0718.md new file mode 100644 index 0000000000..8548ff0c15 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0718.md @@ -0,0 +1,11 @@ +This error indicates that a `#[lang = ".."]` attribute was placed +on the wrong type of item. + +Examples of erroneous code: + +```compile_fail,E0718 +#![feature(lang_items)] + +#[lang = "arc"] +static X: u32 = 42; +``` diff --git a/src/librustc_error_codes/error_codes/E0720.md b/src/librustc_error_codes/error_codes/E0720.md new file mode 100644 index 0000000000..410aa4f460 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0720.md @@ -0,0 +1,11 @@ +An `impl Trait` type expands to a recursive type. + +An `impl Trait` type must be expandable to a concrete type that contains no +`impl Trait` types. For example the following example tries to create an +`impl Trait` type `T` that is equal to `[T, T]`: + +```compile_fail,E0720 +fn make_recursive_type() -> impl Sized { + [make_recursive_type(), make_recursive_type()] +} +``` diff --git a/src/librustc_error_codes/error_codes/E0723.md b/src/librustc_error_codes/error_codes/E0723.md new file mode 100644 index 0000000000..394ee057b0 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0723.md @@ -0,0 +1,28 @@ +An feature unstable in `const` contexts was used. + +Erroneous code example: + +```compile_fail,E0723 +trait T {} + +impl T for () {} + +const fn foo() -> impl T { // error: `impl Trait` in const fn is unstable + () +} +``` + +To enable this feature on a nightly version of rustc, add the `const_fn` +feature flag: + +``` +#![feature(const_fn)] + +trait T {} + +impl T for () {} + +const fn foo() -> impl T { + () +} +``` diff --git a/src/librustc_error_codes/error_codes/E0725.md b/src/librustc_error_codes/error_codes/E0725.md new file mode 100644 index 0000000000..9bd321e5f8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0725.md @@ -0,0 +1,12 @@ +A feature attribute named a feature that was disallowed in the compiler +command line flags. + +Erroneous code example: + +```ignore (can't specify compiler flags from doctests) +#![feature(never_type)] // error: the feature `never_type` is not in + // the list of allowed features +``` + +Delete the offending feature attribute, or add it to the list of allowed +features in the `-Z allow_features` flag. diff --git a/src/librustc_error_codes/error_codes/E0728.md b/src/librustc_error_codes/error_codes/E0728.md new file mode 100644 index 0000000000..1afbedab0c --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0728.md @@ -0,0 +1,75 @@ +[`await`] has been used outside [`async`] function or block. + +Erroneous code examples: + +```edition2018,compile_fail,E0728 +# use std::pin::Pin; +# use std::future::Future; +# use std::task::{Context, Poll}; +# +# struct WakeOnceThenComplete(bool); +# +# fn wake_and_yield_once() -> WakeOnceThenComplete { +# WakeOnceThenComplete(false) +# } +# +# impl Future for WakeOnceThenComplete { +# type Output = (); +# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { +# if self.0 { +# Poll::Ready(()) +# } else { +# cx.waker().wake_by_ref(); +# self.0 = true; +# Poll::Pending +# } +# } +# } +# +fn foo() { + wake_and_yield_once().await // `await` is used outside `async` context +} +``` + +[`await`] is used to suspend the current computation until the given +future is ready to produce a value. So it is legal only within +an [`async`] context, like an `async fn` or an `async` block. + +```edition2018 +# use std::pin::Pin; +# use std::future::Future; +# use std::task::{Context, Poll}; +# +# struct WakeOnceThenComplete(bool); +# +# fn wake_and_yield_once() -> WakeOnceThenComplete { +# WakeOnceThenComplete(false) +# } +# +# impl Future for WakeOnceThenComplete { +# type Output = (); +# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { +# if self.0 { +# Poll::Ready(()) +# } else { +# cx.waker().wake_by_ref(); +# self.0 = true; +# Poll::Pending +# } +# } +# } +# +async fn foo() { + wake_and_yield_once().await // `await` is used within `async` function +} + +fn bar(x: u8) -> impl Future { + async move { + wake_and_yield_once().await; // `await` is used within `async` block + x + } +} +``` + +[`async`]: https://doc.rust-lang.org/std/keyword.async.html +[`await`]: https://doc.rust-lang.org/std/keyword.await.html diff --git a/src/librustc_error_codes/error_codes/E0729.md b/src/librustc_error_codes/error_codes/E0729.md new file mode 100644 index 0000000000..74f89080b9 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0729.md @@ -0,0 +1,30 @@ +Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler +since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow +checker for NLL uncovered some bugs in the old borrow checker, which in some +cases allowed unsound code to compile, resulting in memory safety issues. + +### What do I do? + +Change your code so the warning does no longer trigger. For backwards +compatibility, this unsound code may still compile (with a warning) right now. +However, at some point in the future, the compiler will no longer accept this +code and will throw a hard error. + +### Shouldn't you fix the old borrow checker? + +The old borrow checker has known soundness issues that are basically impossible +to fix. The new NLL-based borrow checker is the fix. + +### Can I turn these warnings into errors by denying a lint? + +No. + +### When are these warnings going to turn into errors? + +No formal timeline for turning the warnings into errors has been set. See +[GitHub issue 58781](https://github.com/rust-lang/rust/issues/58781) for more +information. + +### Why do I get this message with code that doesn't involve borrowing? + +There are some known bugs that trigger this message. diff --git a/src/librustc_error_codes/error_codes/E0730.md b/src/librustc_error_codes/error_codes/E0730.md new file mode 100644 index 0000000000..803a251486 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0730.md @@ -0,0 +1,29 @@ +An array without a fixed length was pattern-matched. + +Example of erroneous code: + +```compile_fail,E0730 +#![feature(const_generics)] + +fn is_123(x: [u32; N]) -> bool { + match x { + [1, 2, 3] => true, // error: cannot pattern-match on an + // array without a fixed length + _ => false + } +} +``` + +Ensure that the pattern is consistent with the size of the matched +array. Additional elements can be matched with `..`: + +``` +#![feature(slice_patterns)] + +let r = &[1, 2, 3, 4]; +match r { + &[a, b, ..] => { // ok! + println!("a={}, b={}", a, b); + } +} +``` diff --git a/src/librustc_error_codes/error_codes/E0731.md b/src/librustc_error_codes/error_codes/E0731.md new file mode 100644 index 0000000000..096c053fe8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0731.md @@ -0,0 +1,17 @@ +An enum with the representation hint `repr(transparent)` had zero or more than +one variants. + +Erroneous code example: + +```compile_fail,E0731 +#[repr(transparent)] +enum Status { // error: transparent enum needs exactly one variant, but has 2 + Errno(u32), + Ok, +} +``` + +Because transparent enums are represented exactly like one of their variants at +run time, said variant must be uniquely determined. If there is no variant, or +if there are multiple variants, it is not clear how the enum should be +represented. diff --git a/src/librustc_error_codes/error_codes/E0732.md b/src/librustc_error_codes/error_codes/E0732.md new file mode 100644 index 0000000000..03137590e8 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0732.md @@ -0,0 +1,29 @@ +An `enum` with a discriminant must specify a `#[repr(inttype)]`. + +A `#[repr(inttype)]` must be provided on an `enum` if it has a non-unit +variant with a discriminant, or where there are both unit variants with +discriminants and non-unit variants. This restriction ensures that there +is a well-defined way to extract a variant's discriminant from a value; +for instance: + +``` +#![feature(arbitrary_enum_discriminant)] + +#[repr(u8)] +enum Enum { + Unit = 3, + Tuple(u16) = 2, + Struct { + a: u8, + b: u16, + } = 1, +} + +fn discriminant(v : &Enum) -> u8 { + unsafe { *(v as *const Enum as *const u8) } +} + +assert_eq!(3, discriminant(&Enum::Unit)); +assert_eq!(2, discriminant(&Enum::Tuple(5))); +assert_eq!(1, discriminant(&Enum::Struct{a: 7, b: 11})); +``` diff --git a/src/librustc_error_codes/error_codes/E0733.md b/src/librustc_error_codes/error_codes/E0733.md new file mode 100644 index 0000000000..0bda7a7d68 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0733.md @@ -0,0 +1,40 @@ +Recursion in an `async fn` requires boxing. For example, this will not compile: + +```edition2018,compile_fail,E0733 +async fn foo(n: usize) { + if n > 0 { + foo(n - 1).await; + } +} +``` + +To achieve async recursion, the `async fn` needs to be desugared +such that the `Future` is explicit in the return type: + +```edition2018,compile_fail,E0720 +use std::future::Future; +fn foo_desugared(n: usize) -> impl Future { + async move { + if n > 0 { + foo_desugared(n - 1).await; + } + } +} +``` + +Finally, the future is wrapped in a pinned box: + +```edition2018 +use std::future::Future; +use std::pin::Pin; +fn foo_recursive(n: usize) -> Pin>> { + Box::pin(async move { + if n > 0 { + foo_recursive(n - 1).await; + } + }) +} +``` + +The `Box<...>` ensures that the result is of known size, +and the pin is required to keep it in the same place in memory. diff --git a/src/librustc_error_codes/error_codes/E0734.md b/src/librustc_error_codes/error_codes/E0734.md new file mode 100644 index 0000000000..913801d223 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0734.md @@ -0,0 +1,13 @@ +A stability attribute has been used outside of the standard library. + +Erroneous code examples: + +```compile_fail,E0734 +#[rustc_deprecated(since = "b", reason = "text")] // invalid +#[stable(feature = "a", since = "b")] // invalid +#[unstable(feature = "b", issue = "0")] // invalid +fn foo(){} +``` + +These attributes are meant to only be used by the standard library and are +rejected in your own crates. diff --git a/src/librustc_error_codes/error_codes/E0735.md b/src/librustc_error_codes/error_codes/E0735.md new file mode 100644 index 0000000000..e8268a5836 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0735.md @@ -0,0 +1,11 @@ +Type parameter defaults cannot use `Self` on structs, enums, or unions. + +Erroneous code example: + +```compile_fail,E0735 +struct Foo> { + field1: Option, + field2: Option, +} +// error: type parameters cannot use `Self` in their defaults. +``` diff --git a/src/librustc_error_codes/error_codes/E0736.md b/src/librustc_error_codes/error_codes/E0736.md new file mode 100644 index 0000000000..8a60dc3205 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0736.md @@ -0,0 +1,16 @@ +`#[track_caller]` and `#[naked]` cannot both be applied to the same function. + +Erroneous code example: + +```compile_fail,E0736 +#![feature(track_caller)] + +#[naked] +#[track_caller] +fn foo() {} +``` + +This is primarily due to ABI incompatibilities between the two attributes. +See [RFC 2091] for details on this and other limitations. + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md diff --git a/src/librustc_error_codes/error_codes/E0737.md b/src/librustc_error_codes/error_codes/E0737.md new file mode 100644 index 0000000000..c6553e97b7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0737.md @@ -0,0 +1,14 @@ +`#[track_caller]` requires functions to have the `"Rust"` ABI for implicitly +receiving caller location. See [RFC 2091] for details on this and other +restrictions. + +Erroneous code example: + +```compile_fail,E0737 +#![feature(track_caller)] + +#[track_caller] +extern "C" fn foo() {} +``` + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md diff --git a/src/librustc_error_codes/error_codes/E0738.md b/src/librustc_error_codes/error_codes/E0738.md new file mode 100644 index 0000000000..4c9588ef7b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0738.md @@ -0,0 +1,48 @@ +`#[track_caller]` cannot be used in traits yet. This is due to limitations in +the compiler which are likely to be temporary. See [RFC 2091] for details on +this and other restrictions. + +Erroneous example with a trait method implementation: + +```compile_fail,E0738 +#![feature(track_caller)] + +trait Foo { + fn bar(&self); +} + +impl Foo for u64 { + #[track_caller] + fn bar(&self) {} +} +``` + +Erroneous example with a blanket trait method implementation: + +```compile_fail,E0738 +#![feature(track_caller)] + +trait Foo { + #[track_caller] + fn bar(&self) {} + fn baz(&self); +} +``` + +Erroneous example with a trait method declaration: + +```compile_fail,E0738 +#![feature(track_caller)] + +trait Foo { + fn bar(&self) {} + + #[track_caller] + fn baz(&self); +} +``` + +Note that while the compiler may be able to support the attribute in traits in +the future, [RFC 2091] prohibits their implementation without a follow-up RFC. + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md diff --git a/src/librustc_error_codes/error_codes/E0740.md b/src/librustc_error_codes/error_codes/E0740.md new file mode 100644 index 0000000000..a9eb5f2790 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0740.md @@ -0,0 +1 @@ +A `union` cannot have fields with destructors. diff --git a/src/librustc_error_codes/error_codes/E0741.md b/src/librustc_error_codes/error_codes/E0741.md new file mode 100644 index 0000000000..804260809e --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0741.md @@ -0,0 +1,21 @@ +Only `structural_match` types (that is, types that derive `PartialEq` and `Eq`) +may be used as the types of const generic parameters. + +```compile_fail,E0741 +#![feature(const_generics)] + +struct A; + +struct B; // error! +``` + +To fix this example, we derive `PartialEq` and `Eq`. + +``` +#![feature(const_generics)] + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok! +``` diff --git a/src/librustc_error_codes/error_codes/E0742.md b/src/librustc_error_codes/error_codes/E0742.md new file mode 100644 index 0000000000..fed9f1f4ce --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0742.md @@ -0,0 +1,35 @@ +Visibility is restricted to a module which isn't an ancestor of the current +item. + +Erroneous code example: + +```compile_fail,E0742,edition2018 +pub mod Sea {} + +pub (in crate::Sea) struct Shark; // error! + +fn main() {} +``` + +To fix this error, we need to move the `Shark` struct inside the `Sea` module: + +```edition2018 +pub mod Sea { + pub (in crate::Sea) struct Shark; // ok! +} + +fn main() {} +``` + +Of course, you can do it as long as the module you're referring to is an +ancestor: + +```edition2018 +pub mod Earth { + pub mod Sea { + pub (in crate::Earth) struct Shark; // ok! + } +} + +fn main() {} +``` diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md new file mode 100644 index 0000000000..aaf19d8478 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0743.md @@ -0,0 +1,11 @@ +C-variadic has been used on a non-foreign function. + +Erroneous code example: + +```compile_fail,E0743 +fn foo2(x: u8, ...) {} // error! +``` + +Only foreign functions can use C-variadic (`...`). It is used to give an +undefined number of parameters to a given function (like `printf` in C). The +equivalent in Rust would be to use macros directly. diff --git a/src/librustc_error_codes/error_codes/E0744.md b/src/librustc_error_codes/error_codes/E0744.md new file mode 100644 index 0000000000..602fbc50a7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0744.md @@ -0,0 +1,24 @@ +Control-flow expressions are not allowed inside a const context. + +At the moment, `if` and `match`, as well as the looping constructs `for`, +`while`, and `loop`, are forbidden inside a `const`, `static`, or `const fn`. + +```compile_fail,E0658 +const _: i32 = { + let mut x = 0; + loop { + x += 1; + if x == 4 { + break; + } + } + x +}; +``` + +This will be allowed at some point in the future, but the implementation is not +yet complete. See the tracking issue for [conditionals] or [loops] in a const +context for the current status. + +[conditionals]: https://github.com/rust-lang/rust/issues/49146 +[loops]: https://github.com/rust-lang/rust/issues/52000 diff --git a/src/librustc_error_codes/error_codes/E0745.md b/src/librustc_error_codes/error_codes/E0745.md new file mode 100644 index 0000000000..39bebdcd37 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0745.md @@ -0,0 +1,20 @@ +Cannot take address of temporary value. + +Erroneous code example: + +```compile_fail,E0745 +# #![feature(raw_ref_op)] +fn temp_address() { + let ptr = &raw const 2; // ERROR +} +``` + +To avoid the error, first bind the temporary to a named local variable. + +```ignore (not yet implemented) +# #![feature(raw_ref_op)] +fn temp_address() { + let val = 2; + let ptr = &raw const val; +} +``` diff --git a/src/librustc_error_codes/lib.rs b/src/librustc_error_codes/lib.rs new file mode 100644 index 0000000000..14210fd69a --- /dev/null +++ b/src/librustc_error_codes/lib.rs @@ -0,0 +1,21 @@ +//! This library is used to gather all error codes into one place, +//! the goal being to make their maintenance easier. + +macro_rules! register_diagnostics { + ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( + pub static DIAGNOSTICS: &[(&str, &str)] = &[ + $( (stringify!($ecode), $message), )* + ]; + + $( + pub const $ecode: () = (); + )* + $( + pub const $code: () = (); + )* + ) +} + +mod error_codes; + +pub use error_codes::*; diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 491bc2aa6a..4c5d0178b2 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -6,9 +6,10 @@ //! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/ use syntax_pos::{SourceFile, MultiSpan, Loc}; +use syntax_pos::source_map::SourceMap; use crate::{ Level, CodeSuggestion, Diagnostic, Emitter, - SourceMapperDyn, SubDiagnostic, DiagnosticId + SubDiagnostic, DiagnosticId }; use crate::emitter::FileWithAnnotatedLines; use rustc_data_structures::sync::Lrc; @@ -20,7 +21,7 @@ use annotate_snippets::formatter::DisplayListFormatter; /// Generates diagnostics using annotate-snippet pub struct AnnotateSnippetEmitterWriter { - source_map: Option>, + source_map: Option>, /// If true, hides the longer explanation text short_message: bool, /// If true, will normalize line numbers with `LL` to prevent noise in UI test diffs. @@ -49,7 +50,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { &suggestions); } - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&Lrc> { self.source_map.as_ref() } @@ -61,7 +62,7 @@ impl Emitter for AnnotateSnippetEmitterWriter { /// Collects all the data needed to generate the data structures needed for the /// `annotate-snippets` library. struct DiagnosticConverter<'a> { - source_map: Option>, + source_map: Option>, level: Level, message: String, code: Option, @@ -168,7 +169,7 @@ impl<'a> DiagnosticConverter<'a> { impl AnnotateSnippetEmitterWriter { pub fn new( - source_map: Option>, + source_map: Option>, short_message: bool, external_macro_backtrace: bool, ) -> Self { diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 5a09898f18..744f4a47b6 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -6,7 +6,7 @@ use crate::Applicability; use crate::Level; use crate::snippet::Style; use std::fmt; -use syntax_pos::{MultiSpan, Span}; +use syntax_pos::{MultiSpan, Span, DUMMY_SP}; #[must_use] #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] @@ -17,6 +17,11 @@ pub struct Diagnostic { pub span: MultiSpan, pub children: Vec, pub suggestions: Vec, + + /// This is not used for highlighting or rendering any error message. Rather, it can be used + /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of + /// `span` if there is one. Otherwise, it is `DUMMY_SP`. + pub sort_span: Span, } #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] @@ -47,6 +52,13 @@ impl DiagnosticStyledString { pub fn push_highlighted>(&mut self, t: S) { self.0.push(StringPart::Highlighted(t.into())); } + pub fn push>(&mut self, t: S, highlight: bool) { + if highlight { + self.push_highlighted(t); + } else { + self.push_normal(t); + } + } pub fn normal>(t: S) -> DiagnosticStyledString { DiagnosticStyledString(vec![StringPart::Normal(t.into())]) } @@ -87,6 +99,7 @@ impl Diagnostic { span: MultiSpan::new(), children: vec![], suggestions: vec![], + sort_span: DUMMY_SP, } } @@ -118,6 +131,11 @@ impl Diagnostic { self.level == Level::Cancelled } + /// Set the sorting span. + pub fn set_sort_span(&mut self, sp: Span) { + self.sort_span = sp; + } + /// Adds a span/label to be included in the resulting snippet. /// This label will be shown together with the original span/label used when creating the /// diagnostic, *not* a span added by one of the `span_*` methods. @@ -143,20 +161,21 @@ impl Diagnostic { self } - pub fn note_expected_found(&mut self, - label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found: DiagnosticStyledString) - -> &mut Self - { - self.note_expected_found_extra(label, expected, found, &"", &"") + pub fn note_expected_found( + &mut self, + expected_label: &dyn fmt::Display, + expected: DiagnosticStyledString, + found_label: &dyn fmt::Display, + found: DiagnosticStyledString, + ) -> &mut Self { + self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") } - pub fn note_unsuccessfull_coercion(&mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString) - -> &mut Self - { + pub fn note_unsuccessfull_coercion( + &mut self, + expected: DiagnosticStyledString, + found: DiagnosticStyledString, + ) -> &mut Self { let mut msg: Vec<_> = vec![(format!("required when trying to coerce from type `"), Style::NoStyle)]; @@ -178,30 +197,41 @@ impl Diagnostic { self } - pub fn note_expected_found_extra(&mut self, - label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - expected_extra: &dyn fmt::Display, - found_extra: &dyn fmt::Display) - -> &mut Self - { - let mut msg: Vec<_> = vec![(format!("expected {} `", label), Style::NoStyle)]; + pub fn note_expected_found_extra( + &mut self, + expected_label: &dyn fmt::Display, + expected: DiagnosticStyledString, + found_label: &dyn fmt::Display, + found: DiagnosticStyledString, + expected_extra: &dyn fmt::Display, + found_extra: &dyn fmt::Display, + ) -> &mut Self { + let expected_label = format!("expected {}", expected_label); + let found_label = format!("found {}", found_label); + let (found_padding, expected_padding) = if expected_label.len() > found_label.len() { + (expected_label.len() - found_label.len(), 0) + } else { + (0, found_label.len() - expected_label.len()) + }; + let mut msg: Vec<_> = vec![( + format!("{}{} `", " ".repeat(expected_padding), expected_label), + Style::NoStyle, + )]; msg.extend(expected.0.iter() - .map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); + .map(|x| match *x { + StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), + StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), + })); msg.push((format!("`{}\n", expected_extra), Style::NoStyle)); - msg.push((format!(" found {} `", label), Style::NoStyle)); + msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle)); msg.extend(found.0.iter() - .map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); + .map(|x| match *x { + StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), + StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), + })); msg.push((format!("`{}", found_extra), Style::NoStyle)); - // For now, just attach these as notes + // For now, just attach these as notes. self.highlighted_note(msg); self } @@ -457,6 +487,9 @@ impl Diagnostic { pub fn set_span>(&mut self, sp: S) -> &mut Self { self.span = sp.into(); + if let Some(span) = self.span.primary_span() { + self.sort_span = span; + } self } @@ -465,10 +498,20 @@ impl Diagnostic { self } + pub fn clear_code(&mut self) -> &mut Self { + self.code = None; + self + } + pub fn get_code(&self) -> Option { self.code.clone() } + pub fn set_primary_message>(&mut self, msg: M) -> &mut Self { + self.message[0] = (msg.into(), Style::NoStyle); + self + } + pub fn message(&self) -> String { self.message.iter().map(|i| i.0.as_str()).collect::() } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 40642dd14b..a95c29f8c2 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -195,37 +195,44 @@ impl<'a> DiagnosticBuilder<'a> { self } - forward!(pub fn note_expected_found(&mut self, - label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - ) -> &mut Self); - - forward!(pub fn note_expected_found_extra(&mut self, - label: &dyn fmt::Display, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - expected_extra: &dyn fmt::Display, - found_extra: &dyn fmt::Display, - ) -> &mut Self); - - forward!(pub fn note_unsuccessfull_coercion(&mut self, - expected: DiagnosticStyledString, - found: DiagnosticStyledString, - ) -> &mut Self); + forward!(pub fn note_expected_found( + &mut self, + expected_label: &dyn fmt::Display, + expected: DiagnosticStyledString, + found_label: &dyn fmt::Display, + found: DiagnosticStyledString, + ) -> &mut Self); + + forward!(pub fn note_expected_found_extra( + &mut self, + expected_label: &dyn fmt::Display, + expected: DiagnosticStyledString, + found_label: &dyn fmt::Display, + found: DiagnosticStyledString, + expected_extra: &dyn fmt::Display, + found_extra: &dyn fmt::Display, + ) -> &mut Self); + + forward!(pub fn note_unsuccessfull_coercion( + &mut self, + expected: DiagnosticStyledString, + found: DiagnosticStyledString, + ) -> &mut Self); forward!(pub fn note(&mut self, msg: &str) -> &mut Self); - forward!(pub fn span_note>(&mut self, - sp: S, - msg: &str, - ) -> &mut Self); + forward!(pub fn span_note>( + &mut self, + sp: S, + msg: &str, + ) -> &mut Self); forward!(pub fn warn(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_warn>(&mut self, sp: S, msg: &str) -> &mut Self); forward!(pub fn help(&mut self, msg: &str) -> &mut Self); - forward!(pub fn span_help>(&mut self, - sp: S, - msg: &str, - ) -> &mut Self); + forward!(pub fn span_help>( + &mut self, + sp: S, + msg: &str, + ) -> &mut Self); pub fn multipart_suggestion( &mut self, diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index b153f0f0e8..6fa2a747fd 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -9,25 +9,26 @@ use Destination::*; -use syntax_pos::{SourceFile, Span, MultiSpan}; +use syntax_pos::source_map::SourceMap; +use syntax_pos::{MultiSpan, SourceFile, Span}; +use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; +use crate::styled_buffer::StyledBuffer; +use crate::Level::Error; use crate::{ - Level, CodeSuggestion, Diagnostic, SubDiagnostic, pluralise, - SuggestionStyle, SourceMapper, SourceMapperDyn, DiagnosticId, + pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle, }; -use crate::Level::Error; -use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; -use crate::styled_buffer::StyledBuffer; +use log::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::borrow::Cow; -use std::io::prelude::*; +use std::cmp::{max, min, Reverse}; use std::io; -use std::cmp::{min, max, Reverse}; +use std::io::prelude::*; use std::path::Path; -use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi}; -use termcolor::{WriteColor, Color, Buffer}; +use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream}; +use termcolor::{Buffer, Color, WriteColor}; /// Describes the way the content of the `rendered` field of the json output is generated #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -49,15 +50,22 @@ impl HumanReadableErrorType { pub fn new_emitter( self, dst: Box, - source_map: Option>, + source_map: Option>, teach: bool, terminal_width: Option, external_macro_backtrace: bool, ) -> EmitterWriter { let (short, color_config) = self.unzip(); let color = color_config.suggests_using_colors(); - EmitterWriter::new(dst, source_map, short, teach, color, terminal_width, - external_macro_backtrace) + EmitterWriter::new( + dst, + source_map, + short, + teach, + color, + terminal_width, + external_macro_backtrace, + ) } } @@ -116,15 +124,15 @@ impl Margin { } fn was_cut_right(&self, line_len: usize) -> bool { - let right = if self.computed_right == self.span_right || - self.computed_right == self.label_right - { - // Account for the "..." padding given above. Otherwise we end up with code lines that - // do fit but end in "..." as if they were trimmed. - self.computed_right - 6 - } else { - self.computed_right - }; + let right = + if self.computed_right == self.span_right || self.computed_right == self.label_right { + // Account for the "..." padding given above. Otherwise we end + // up with code lines that do fit but end in "..." as if they + // were trimmed. + self.computed_right - 6 + } else { + self.computed_right + }; right < line_len && self.computed_left + self.column_width < line_len } @@ -155,7 +163,8 @@ impl Margin { let padding_left = (self.column_width - (self.span_right - self.span_left)) / 5 * 2; self.computed_left = self.span_left.saturating_sub(padding_left); self.computed_right = self.computed_left + self.column_width; - } else { // Mostly give up but still don't show the full line. + } else { + // Mostly give up but still don't show the full line. self.computed_left = self.span_left; self.computed_right = self.span_right; } @@ -192,7 +201,7 @@ pub trait Emitter { true } - fn source_map(&self) -> Option<&Lrc>; + fn source_map(&self) -> Option<&Lrc>; /// Formats the substitutions of the primary_span /// @@ -239,11 +248,15 @@ pub trait Emitter { format!( "help: {}{}: `{}`", sugg.msg, - if self.source_map().map(|sm| is_case_difference( - &**sm, - substitution, - sugg.substitutions[0].parts[0].span, - )).unwrap_or(false) { + if self + .source_map() + .map(|sm| is_case_difference( + &**sm, + substitution, + sugg.substitutions[0].parts[0].span, + )) + .unwrap_or(false) + { " (notice the capitalization)" } else { "" @@ -270,37 +283,35 @@ pub trait Emitter { // This does a small "fix" for multispans by looking to see if it can find any that // point directly at <*macros>. Since these are often difficult to read, this // will change the span to point at the use site. - fn fix_multispans_in_std_macros(&self, - source_map: &Option>, - span: &mut MultiSpan, - children: &mut Vec, - level: &Level, - backtrace: bool) { + fn fix_multispans_in_std_macros( + &self, + source_map: &Option>, + span: &mut MultiSpan, + children: &mut Vec, + level: &Level, + backtrace: bool, + ) { let mut spans_updated = self.fix_multispan_in_std_macros(source_map, span, backtrace); for child in children.iter_mut() { - spans_updated |= self.fix_multispan_in_std_macros( - source_map, - &mut child.span, - backtrace - ); + spans_updated |= + self.fix_multispan_in_std_macros(source_map, &mut child.span, backtrace); } let msg = if level == &Error { "this error originates in a macro outside of the current crate \ (in Nightly builds, run with -Z external-macro-backtrace \ - for more info)".to_string() + for more info)" + .to_string() } else { "this warning originates in a macro outside of the current crate \ (in Nightly builds, run with -Z external-macro-backtrace \ - for more info)".to_string() + for more info)" + .to_string() }; if spans_updated { children.push(SubDiagnostic { level: Level::Note, - message: vec![ - (msg, - Style::NoStyle), - ], + message: vec![(msg, Style::NoStyle)], span: MultiSpan::new(), render_span: None, }); @@ -310,10 +321,12 @@ pub trait Emitter { // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of // <*macros>. Since these locations are often difficult to read, we move these Spans from // <*macros> to their corresponding use site. - fn fix_multispan_in_std_macros(&self, - source_map: &Option>, - span: &mut MultiSpan, - always_backtrace: bool) -> bool { + fn fix_multispan_in_std_macros( + &self, + source_map: &Option>, + span: &mut MultiSpan, + always_backtrace: bool, + ) -> bool { let sm = match source_map { Some(ref sm) => sm, None => return false, @@ -339,31 +352,40 @@ pub trait Emitter { continue; } if always_backtrace { - new_labels.push((trace.def_site_span, - format!("in this expansion of `{}`{}", - trace.macro_decl_name, - if backtrace_len > 2 { - // if backtrace_len == 1 it'll be pointed - // at by "in this macro invocation" - format!(" (#{})", i + 1) - } else { - String::new() - }))); + new_labels.push(( + trace.def_site_span, + format!( + "in this expansion of `{}`{}", + trace.macro_decl_name, + if backtrace_len > 2 { + // if backtrace_len == 1 it'll be pointed + // at by "in this macro invocation" + format!(" (#{})", i + 1) + } else { + String::new() + } + ), + )); } // Check to make sure we're not in any <*macros> - if !sm.span_to_filename(trace.def_site_span).is_macros() && - !trace.macro_decl_name.starts_with("desugaring of ") && - !trace.macro_decl_name.starts_with("#[") || - always_backtrace { - new_labels.push((trace.call_site, - format!("in this macro invocation{}", - if backtrace_len > 2 && always_backtrace { - // only specify order when the macro - // backtrace is multiple levels deep - format!(" (#{})", i + 1) - } else { - String::new() - }))); + if !sm.span_to_filename(trace.def_site_span).is_macros() + && !trace.macro_decl_name.starts_with("desugaring of ") + && !trace.macro_decl_name.starts_with("#[") + || always_backtrace + { + new_labels.push(( + trace.call_site, + format!( + "in this macro invocation{}", + if backtrace_len > 2 && always_backtrace { + // only specify order when the macro + // backtrace is multiple levels deep + format!(" (#{})", i + 1) + } else { + String::new() + } + ), + )); if !always_backtrace { break; } @@ -377,9 +399,7 @@ pub trait Emitter { if sp_label.span.is_dummy() { continue; } - if sm.span_to_filename(sp_label.span.clone()).is_macros() && - !always_backtrace - { + if sm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace { let v = sp_label.span.macro_backtrace(); if let Some(use_site) = v.last() { before_after.push((sp_label.span.clone(), use_site.call_site.clone())); @@ -397,7 +417,7 @@ pub trait Emitter { } impl Emitter for EmitterWriter { - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&Lrc> { self.sm.as_ref() } @@ -405,18 +425,22 @@ impl Emitter for EmitterWriter { let mut children = diag.children.clone(); let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); - self.fix_multispans_in_std_macros(&self.sm, - &mut primary_span, - &mut children, - &diag.level, - self.external_macro_backtrace); - - self.emit_messages_default(&diag.level, - &diag.styled_message(), - &diag.code, - &primary_span, - &children, - &suggestions); + self.fix_multispans_in_std_macros( + &self.sm, + &mut primary_span, + &mut children, + &diag.level, + self.external_macro_backtrace, + ); + + self.emit_messages_default( + &diag.level, + &diag.styled_message(), + &diag.code, + &primary_span, + &children, + &suggestions, + ); } fn should_show_explain(&self) -> bool { @@ -424,6 +448,16 @@ impl Emitter for EmitterWriter { } } +/// An emitter that does nothing when emitting a diagnostic. +pub struct SilentEmitter; + +impl Emitter for SilentEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } + fn emit_diagnostic(&mut self, _: &Diagnostic) {} +} + /// maximum number of lines we will print for each error; arbitrary. pub const MAX_HIGHLIGHT_LINES: usize = 6; /// maximum number of suggestions to be shown @@ -449,17 +483,13 @@ impl ColorConfig { } } ColorConfig::Never => ColorChoice::Never, - ColorConfig::Auto if atty::is(atty::Stream::Stderr) => { - ColorChoice::Auto - } + ColorConfig::Auto if atty::is(atty::Stream::Stderr) => ColorChoice::Auto, ColorConfig::Auto => ColorChoice::Never, } } fn suggests_using_colors(self) -> bool { match self { - | ColorConfig::Always - | ColorConfig::Auto - => true, + ColorConfig::Always | ColorConfig::Auto => true, ColorConfig::Never => false, } } @@ -468,7 +498,7 @@ impl ColorConfig { /// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` pub struct EmitterWriter { dst: Destination, - sm: Option>, + sm: Option>, short_message: bool, teach: bool, ui_testing: bool, @@ -487,7 +517,7 @@ pub struct FileWithAnnotatedLines { impl EmitterWriter { pub fn stderr( color_config: ColorConfig, - source_map: Option>, + source_map: Option>, short_message: bool, teach: bool, terminal_width: Option, @@ -507,7 +537,7 @@ impl EmitterWriter { pub fn new( dst: Box, - source_map: Option>, + source_map: Option>, short_message: bool, teach: bool, colored: bool, @@ -531,11 +561,7 @@ impl EmitterWriter { } fn maybe_anonymized(&self, line_num: usize) -> String { - if self.ui_testing { - ANONYMIZED_LINE_NUM.to_string() - } else { - line_num.to_string() - } + if self.ui_testing { ANONYMIZED_LINE_NUM.to_string() } else { line_num.to_string() } } fn draw_line( @@ -554,17 +580,22 @@ impl EmitterWriter { let right = margin.right(line_len); // On long lines, we strip the source line, accounting for unicode. let mut taken = 0; - let code: String = source_string.chars().skip(left).take_while(|ch| { - // Make sure that the trimming on the right will fall within the terminal width. - // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. - // For now, just accept that sometimes the code line will be longer than desired. - let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); - if taken + next > right - left { - return false; - } - taken += next; - true - }).collect(); + let code: String = source_string + .chars() + .skip(left) + .take_while(|ch| { + // Make sure that the trimming on the right will fall within the + // terminal width. FIXME: `unicode_width` sometimes disagrees + // with terminals on how wide a `char` is. For now, just accept + // that sometimes the code line will be longer than desired. + let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); + if taken + next > right - left { + return false; + } + taken += next; + true + }) + .collect(); buffer.puts(line_offset, code_offset, &code, Style::Quotation); if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. @@ -615,7 +646,9 @@ impl EmitterWriter { let left = margin.left(source_string.len()); // Left trim // Account for unicode characters of width !=0 that were removed. - let left = source_string.chars().take(left) + let left = source_string + .chars() + .take(left) .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) .sum(); @@ -764,13 +797,14 @@ impl EmitterWriter { if overlaps(next, annotation, 0) // This label overlaps with another one and both && annotation.has_label() // take space (they have text and are not && j > i // multiline lines). - && p == 0 // We're currently on the first line, move the label one line down + && p == 0 + // We're currently on the first line, move the label one line down { // If we're overlapping with an un-labelled annotation with the same span // we can just merge them in the output if next.start_col == annotation.start_col - && next.end_col == annotation.end_col - && !next.has_label() + && next.end_col == annotation.end_col + && !next.has_label() { continue; } @@ -782,7 +816,7 @@ impl EmitterWriter { } annotations_position.push((p, annotation)); for (j, next) in annotations.iter().enumerate() { - if j > i { + if j > i { let l = next.label.as_ref().map_or(0, |label| label.len() + 2); if (overlaps(next, annotation, l) // Do not allow two labels to be in the same // line if they overlap including padding, to @@ -805,7 +839,8 @@ impl EmitterWriter { || (overlaps(next, annotation, l) && next.end_col <= annotation.end_col && next.has_label() - && p == 0) // Avoid #42595. + && p == 0) + // Avoid #42595. { // This annotation needs a new line in the output. p += 1; @@ -826,7 +861,7 @@ impl EmitterWriter { return vec![]; } - // Write the colunmn separator. + // Write the column separator. // // After this we will have: // @@ -839,10 +874,7 @@ impl EmitterWriter { // | for pos in 0..=line_len { draw_col_separator(buffer, line_offset + pos + 1, width_offset - 2); - buffer.putc(line_offset + pos + 1, - width_offset - 2, - '|', - Style::LineNumber); + buffer.putc(line_offset + pos + 1, width_offset - 2, '|', Style::LineNumber); } // Write the horizontal lines for multiline annotations @@ -865,8 +897,7 @@ impl EmitterWriter { }; let pos = pos + 1; match annotation.annotation_type { - AnnotationType::MultilineStart(depth) | - AnnotationType::MultilineEnd(depth) => { + AnnotationType::MultilineStart(depth) | AnnotationType::MultilineEnd(depth) => { draw_range( buffer, '_', @@ -897,7 +928,7 @@ impl EmitterWriter { // | __________ // | | | // | | - // 3 | + // 3 | | // 4 | | } // | |_ for &(pos, annotation) in &annotations_position { @@ -910,27 +941,23 @@ impl EmitterWriter { if pos > 1 && (annotation.has_label() || annotation.takes_space()) { for p in line_offset + 1..=line_offset + pos { - buffer.putc(p, - code_offset + annotation.start_col - margin.computed_left, - '|', - style); + buffer.putc( + p, + (code_offset + annotation.start_col).saturating_sub(left), + '|', + style, + ); } } match annotation.annotation_type { AnnotationType::MultilineStart(depth) => { for p in line_offset + pos + 1..line_offset + line_len + 2 { - buffer.putc(p, - width_offset + depth - 1, - '|', - style); + buffer.putc(p, width_offset + depth - 1, '|', style); } } AnnotationType::MultilineEnd(depth) => { for p in line_offset..=line_offset + pos { - buffer.putc(p, - width_offset + depth - 1, - '|', - style); + buffer.putc(p, width_offset + depth - 1, '|', style); } } _ => (), @@ -949,11 +976,8 @@ impl EmitterWriter { // 4 | } // | _ test for &(pos, annotation) in &annotations_position { - let style = if annotation.is_primary { - Style::LabelPrimary - } else { - Style::LabelSecondary - }; + let style = + if annotation.is_primary { Style::LabelPrimary } else { Style::LabelSecondary }; let (pos, col) = if pos == 0 { (pos + 1, (annotation.end_col + 1).saturating_sub(left)) } else { @@ -1003,8 +1027,9 @@ impl EmitterWriter { ); } } - annotations_position.iter().filter_map(|&(_, annotation)| { - match annotation.annotation_type { + annotations_position + .iter() + .filter_map(|&(_, annotation)| match annotation.annotation_type { AnnotationType::MultilineStart(p) | AnnotationType::MultilineEnd(p) => { let style = if annotation.is_primary { Style::LabelPrimary @@ -1013,10 +1038,9 @@ impl EmitterWriter { }; Some((p, style)) } - _ => None - } - - }).collect::>() + _ => None, + }) + .collect::>() } fn get_multispan_max_line_num(&mut self, msp: &MultiSpan) -> usize { @@ -1046,7 +1070,8 @@ impl EmitterWriter { fn get_max_line_num(&mut self, span: &MultiSpan, children: &[SubDiagnostic]) -> usize { let primary = self.get_multispan_max_line_num(span); - children.iter() + children + .iter() .map(|sub| self.get_multispan_max_line_num(&sub.span)) .max() .unwrap_or(0) @@ -1055,13 +1080,14 @@ impl EmitterWriter { /// Adds a left margin to every line but the first, given a padding length and the label being /// displayed, keeping the provided highlighting. - fn msg_to_buffer(&self, - buffer: &mut StyledBuffer, - msg: &[(String, Style)], - padding: usize, - label: &str, - override_style: Option